Part 2 - Repository Layout¶
Where things live in OpenZFS, and how to find the right code quickly.
Introduction¶
Part 1 gave us the architecture mental model. This chapter maps that model to real directories.
This is the practical question we are answering:
- "I know what subsystem I care about, but where is that code in the tree?"
All paths in this chapter are relative to an OpenZFS checkout root (for example zfs/ from git clone https://github.com/openzfs/zfs.git).
Snapshot counts at the pinned reference revision (see README; they drift as OpenZFS evolves, but the shape stays the same):
module/zfs: 138.cfilesmodule/zcommon: 17.cfilesmodule/os/linux/zfs: 34.cfilesinclude/sys: 140 headerstests/zfs-tests/tests/functional: 105 test categories
How To Use This Map¶
There are three axes you should keep in your head while navigating:
- Runtime context: kernel, shared, or userland.
- Platform scope: portable core vs OS-specific integration.
- Subsystem ownership: SPA, DMU, DSL, ARC, ZIO, VDEV, ZIL, etc.
If you identify all three, you usually find the right directory in one jump.
Diagram 1 - Runtime Boundaries¶
graph TD
subgraph KERNEL["Kernel code"]
MZFS["module/zfs<br/>portable core subsystems"]
MOSLIN["module/os/linux/zfs<br/>Linux glue and VFS integration"]
MOSFB["module/os/freebsd/zfs<br/>FreeBSD glue and VFS integration"]
end
subgraph SHARED["Shared code"]
MZCOMMON["module/zcommon<br/>shared tables/definitions"]
INCSYS["include/sys<br/>core headers"]
INCROOT["include/<br/>shared root headers (for example zfeature_common.h)"]
end
subgraph USERLAND["Userland code"]
LIB["lib/<br/>libzfs, libzfs_core, libzpool, ..."]
CMD["cmd/<br/>zfs, zpool, zdb, ztest, zhack, ..."]
TESTS["tests/<br/>zfs-tests and test-runner"]
end
CMD --> LIB
LIB --> INCSYS
LIB --> INCROOT
MZFS --> INCSYS
MOSLIN --> INCSYS
MOSFB --> INCSYS
MZCOMMON --> INCSYS
MZCOMMON --> INCROOT
style MZFS fill:#d9f7d6,stroke:#333
style MOSLIN fill:#d7ecff,stroke:#333
style MOSFB fill:#d7ecff,stroke:#333
style MZCOMMON fill:#fff4c2,stroke:#333
style LIB fill:#f7d9ff,stroke:#333
style CMD fill:#f7d9ff,stroke:#333
style TESTS fill:#ffe8cc,stroke:#333
Top-Level Tree (What Each Folder Is For)¶
openzfs/
├── cmd/ user-facing binaries and tools
├── config/ build-system configuration and probes
├── contrib/ optional integrations and external helpers
├── etc/ init/service/runtime config templates
├── include/ headers used across kernel and userland
├── lib/ userland libraries
├── man/ man pages
├── module/ kernel code (portable + OS-specific)
├── rpm/ RPM packaging assets
├── scripts/ build and developer scripts
├── tests/ test framework and zfs-tests
└── udev/ udev rules for Linux device handling
Two practical anchors:
- If you are debugging behavior, start in
module/. - If you are changing CLI behavior, start in
cmd/and usually also touchlib/.
module/zfs/ - Portable Core Kernel Implementation¶
This is the heart of OpenZFS core logic.
Important point:
module/zfs/is organized mostly by subsystem, not by tutorial layer order.
High-value subsystem anchors:
- Pool and txg orchestration:
spa.c,spa_misc.c,txg.c - Object and transaction core:
dmu.c,dmu_tx.c,dnode.c,dmu_objset.c - Dataset/snapshot semantics:
dsl_dataset.c,dsl_dir.c,dsl_pool.c - Send/receive replication:
dmu_send.c,dmu_recv.c - Cache and buffers:
arc.c,dbuf.c,abd.c - I/O engine and integrity:
zio.c,zio_checksum.c,zio_compress.c - Allocation and free-space management:
metaslab.c,space_map.c,range_tree.c - Storage topology and dispatch:
vdev.c,vdev_queue.c,vdev_mirror.c,vdev_raidz.c - Intent logging:
zil.c - Attribute/object stores:
zap.c,zap_micro.c,zap_leaf.c
When in doubt:
- Find the subsystem noun in the file name (
spa_,dsl_,dmu_,vdev_,zio_).
module/os/linux/zfs/ and module/os/freebsd/ - OS Integration¶
This is where OpenZFS connects to each OS kernel's VFS and device interfaces.
Linux path:
module/os/linux/zfs/zpl_file.c,zpl_inode.c,zpl_super.cmodule/os/linux/zfs/zfs_vnops_os.c,zfs_vfsops.cmodule/os/linux/zfs/vdev_disk.c
Key distinction that trips people up:
- Core vnode operations (
zfs_read,zfs_write) are inmodule/zfs/zfs_vnops.c. - Linux-specific wrappers and integration paths are in
module/os/linux/zfs/zfs_vnops_os.c.
Use this directory when behavior depends on Linux kernel interfaces, credentials, inode rules, mount plumbing, or block-layer specifics.
Sibling directory worth knowing: module/os/linux/spl/ is the kernel
Solaris Portability Layer. It implements Solaris-style primitives (taskqs,
kmem caches, kstats, condvars, TSD, ...) on top of Linux kernel APIs, in
files named spl-*.c (spl-taskq.c, spl-kmem.c, spl-kstat.c). It is
Linux-only; FreeBSD supplies its own equivalents under
module/os/freebsd/spl/. The userland counterpart is lib/libspl/, which
provides the same Solaris-style shims to tools and libraries (see the lib/
section below).
module/zcommon/ - Shared Tables and Common Definitions¶
module/zcommon/ is compiled into multiple targets and holds code intentionally shared across boundaries.
Examples:
zfeature_common.cfor feature registration tableszfs_prop.c,zpool_prop.c,zprop_common.cfor property definitions- checksum/property utility code used by more than one build target
If you are adding a new pool feature or property, this directory is almost always involved.
Other module/ Subdirectories - Embedded Support Code¶
module/zfs/ and the module/os/ trees are not the whole kernel build.
These siblings hold support code, most of them kernel-side counterparts of
like-named userland libraries in lib/:
module/avl/: AVL tree implementation used across subsystems (userland twin:lib/libavl/).module/nvpair/: name-value pair encoding used for configs, properties, and ioctl payloads (userland twin:lib/libnvpair/).module/icp/: Illumos Crypto Provider; supplies the crypto primitives behind dataset encryption and cryptographic checksums (userland twin:lib/libicp/).module/lua/: embedded Lua interpreter that executes channel programs (zfs program); the ZFS-side glue ismodule/zfs/zcp*.c.module/zstd/: vendored Zstandard library plus glue (zfs_zstd.c) forcompression=zstd(userland twin:lib/libzstd/).
include/ and include/sys/ - Header Ground Truth¶
include/sys/ mirrors core subsystems and is the fastest way to find major types:
- SPA:
spa.h,spa_impl.h - DMU:
dmu.h,dmu_tx.h,dnode.h - DSL:
dsl_dataset.h,dsl_pool.h,dsl_dir.h - ZIO:
zio.h,zio_impl.h - VDEV:
vdev.h,vdev_impl.h - ARC/dbuf:
arc.h,arc_impl.h,dbuf.h
Headers also mirror the module/os/ split:
include/os/linux/(withkernel/,spl/, andzfs/subtrees) holds Linux-specific headers.include/os/freebsd/(withspl/andzfs/subtrees, plus a smalllinux/compat-shim directory) holds the FreeBSD side.
The usual pattern is a portable contract in include/sys/ with a platform half under include/os/<platform>/.../sys/, distinguished by name: include/sys/zfs_znode.h (portable) pairs with include/os/linux/zfs/sys/zfs_znode_impl.h (Linux), and zfs_vnops_os.h / zpl.h live only on the OS side.
One gotcha worth remembering:
include/zfeature_common.his atinclude/root, notinclude/sys/.
lib/ - Userland Libraries¶
lib/ provides the userland API and tooling substrate. At the pinned reference revision there are 12 top-level libraries (current master has since added libbtree/ and librange_tree/, userland builds of the like-named kernel data structures):
libzfs/(high-level administrative API used byzfs/zpool)libzfs_core/(lower-level ioctl interface for programmatic control)libzpool/(kernel-style core logic built for userland tools likezdb/ztest)libzutil/(shared utility helpers used across OpenZFS userland)libzdb/(helpers specific tozdbinspection logic)libnvpair/(name-value pair encoding used in pool and feature metadata)libspl/(Solaris Portability Layer shims for userland/kernel portability)libavl/(AVL tree implementation reused across subsystems)libefi/(EFI/GPT-related helpers)libicp/(cryptography provider pieces used by encryption/checksum paths)libzfsbootenv/(boot environment support helpers)libzstd/(vendored Zstandard compression library integration)
How to think about the most commonly touched ones:
libzfs: high-level administrative API used byzfsandzpool.libzfs_core: lower-level ioctl-driven interface.libzpool: kernel-style logic linked into userland tools likezdb/ztest.
cmd/ - Binaries and Developer Tools¶
cmd/ contains both end-user commands and contributor-oriented tools.
Core admin and inspection tools:
cmd/zfs/cmd/zpool/cmd/zdb/cmd/zed/
Contributor tools you will use often:
cmd/zhack.cfor format and feature experimentscmd/ztest.cfor stress and race testingcmd/zinject/for fault injectioncmd/zstream/for send/receive stream work
tests/ - Test Framework and Suites¶
Primary areas:
tests/test-runner/for execution frameworktests/runfiles/for suite selectiontests/zfs-tests/tests/functional/for functional tests (105 categories)tests/zfs-tests/tests/perf/for performance tests
If you add behavior:
- expect to touch
tests/zfs-tests/tests/functional/<category>/.
contrib/ - Integrations and External Helpers¶
contrib/ is for optional integrations and bundled support artifacts that are not the core portable engine.
In this checkout it includes areas such as:
contrib/dracut/,contrib/initramfs/,contrib/debian/for distro/initramfs integrationcontrib/bash_completion.d/for shell completion assetscontrib/pyzfs/for Python bindings/utilitiescontrib/bpftrace/for tracing scriptscontrib/pam_zfs_key/for PAM integration
If you are changing core filesystem behavior, you usually will not start here. If you are packaging, bootstrapping, or integrating OpenZFS into system environments, this directory becomes important quickly.
Build and Packaging Directories¶
These are less exciting but important:
config/andscripts/: configure probes, build helper logicman/: canonical user-facing documentation updatesetc/: init/service and runtime config templates (pool feature compatibility files live incmd/zpool/compatibility.d/)udev/: Linux device rule integrationrpm/: packaging metadata
Many PRs are blocked in review because code changed but man pages or compatibility files were not updated.
Diagram 2 - "Where Do I Start?" Task Map¶
flowchart TD
Q["What are you changing?"]
Q --> A["File I/O behavior"]
Q --> B["Pool layout/allocation"]
Q --> C["Feature flag or property"]
Q --> D["CLI output/UX"]
Q --> E["Test failure only on Linux"]
A --> A1["module/os/linux/zfs/zpl_file.c"]
A --> A2["module/zfs/zfs_vnops.c"]
A --> A3["module/zfs/dmu*.c"]
B --> B1["module/zfs/zio.c"]
B --> B2["module/zfs/metaslab.c"]
B --> B3["module/zfs/vdev*.c"]
C --> C1["include/zfeature_common.h"]
C --> C2["module/zcommon/zfeature_common.c"]
C --> C3["module/zcommon/zfs_prop.c or zpool_prop.c"]
D --> D1["cmd/zfs or cmd/zpool"]
D --> D2["lib/libzfs"]
D --> D3["man/"]
E --> E1["module/os/linux/zfs/*"]
E --> E2["tests/zfs-tests/*"]
style Q fill:#f5f5f5,stroke:#333
style A fill:#d7ecff,stroke:#333
style B fill:#d9f7d6,stroke:#333
style C fill:#fff4c2,stroke:#333
style D fill:#f7d9ff,stroke:#333
style E fill:#ffe8cc,stroke:#333
Common Navigation Traps¶
module/zfs/zfs_vnops.cvsmodule/os/linux/zfs/zfs_vnops_os.c:zfs_vnops.cis core vnode logic;zfs_vnops_os.cis Linux glue.include/zfeature_common.hlocation: it lives underinclude/, notinclude/sys/.libzpoolcontext: it is userland, but reads like kernel code by design.module/zcommon/role: shared code, not "misc leftovers."- Test location assumptions:
most behavior tests are in
tests/zfs-tests/tests/functional/, not under subsystem directories inmodule/.
Practical Reading Order (Layout-Oriented)¶
Use this pass when your goal is orientation rather than deep subsystem mastery:
For a call-flow-oriented reading order (foreground path, txg sync, and durable commit semantics), see Part 1's reading order.
- Top-level tree (
cmd,lib,module,include,tests) module/zfs/high-level file scan (spa*,dmu*,dsl*,zio*,vdev*)module/os/linux/zfs/for OS boundary understandinginclude/sys/for type and API anchorsmodule/zcommon/for shared definitionscmd/+lib/pairings for userland behaviortests/zfs-tests/tests/functional/categories for coverage map
Next¶
-> Part 3 - The I/O Path: trace a write end-to-end with concrete function-level control flow.