XXNU Source Handbook Offline reading instructions
Part 10 · Chapter 10.01

VFS, filesystems, and storage I/O

Guide index · Architecture

The virtual filesystem layer connects BSD file operations, pathname resolution, filesystem implementations, VM-backed file contents and device I/O. Its central object is the vnode: an in-memory handle for a filesystem object, with an operation vector and filesystem-private state. A vnode can represent a regular file, directory, device, FIFO, socket or other supported object; it is not synonymous with an on-disk inode.

Read vnodes, mounts and dispatch first. Then follow pathname lookup and authorization, file data and I/O completion, and the in-tree filesystems and NFS survey. The VM chapter covers the other side of file-backed mappings and page faults.

The mapped-file worked operation connects these paths: descriptor lookup and release, vnode/UBC/pager identity, a cold read fault, private COW write, ARM64 translation and unmapping. Its file coordinate remains explicit across clustered page-in and changing VM object offsets.

Continue into the detailed implementation chapters:

Chapter Main questions answered
Vnode permissions and ACL evaluation How do action masks, mount/immutable restrictions, ordered ACEs, group resolution, POSIX fallback, parent deletion rights and inheritance determine authorization?
Name-cache validation and vnode reclamation How do SMR snapshots become generation-checked I/O references? How are names published and invalidated? What drains, cleans and recycles a vnode?
Vnode cache identity and reuse What remains cached after close? How do free/age/dead lists, identity generations, filesystem lookup and authorization caching interact?
File-data cache and read paths How do UBC, the vnode pager and VM pages supply resident reads, cache misses, read-ahead, mappings, truncation and invalidation?
Buffer cache and block I/O How do buffer hashes, busy ownership, free queues, backing storage, delayed writes and completion differ from cached file pages?
Mount publication, traversal and unmount Why do busy locks, ordinary references, iteration references and cross-references differ? How does lookup cross a mount, and what survives a failed unmount?
Clustered writes, dirty tracking and I/O completion How are writes grouped or tracked sparsely? Why are UPLs released and reacquired? How do direct writes, buffer callbacks, partial failures and synchronous pushes complete?
Namespace mutations and compound operations How do create, link, unlink and rename authorize changes, relookup after locking, continue compound lookup and publish identity/events?
Device nodes, specfs and named FIFOs How do devfs names become vnodes, clone devices get instances, device aliases reach the switch, and FIFO socket pairs open and close?
Stacked filesystems How do bindfs/nullfs retain lower vnodes, resolve alias-creation races, synthesize identity, forward page-in and unmount?
NFS server requests How do socket records become requests, bounded replay caches filter duplicates, file handles resolve, and READ/WRITE/gather/COMMIT complete?
Attribute lists and extended attributes How are metadata bitmaps authorized, fetched, packed and set? How do native xattrs and the DoubleAgent fallback transfer data and references?
Advisory locks and leases Who owns a byte-range lock, how are intervals and waiters updated, and how do lease breaks notify, wait, time out and reclaim?
Filesystem event queues How do producers, shared events, per-watcher rings, coalescing, loss markers, record copies and close interact?
Compressed file data How do decmpfs headers/providers, cnode state, resident pages, UPL completion and conversion to ordinary backing work?
Quota records and cache lifetime How do quota-file exclusion, record lookup/reuse, on-disk hashing, dirty orphan writeback and filesystem callbacks fit together?

For signed files, continue from those caches into signature format and structural checks → attachment to the vnode's UBC state → exec and mapping policy → page hashing and cached validation. A name-cache hit, a resident data page, an accepted cs_blob, and an executable mapping are separate results.

The file structure route connects descriptor tables and fileproc/fileglob storage to vnode identity, UBC/pager allocation and lifetime, and RO signature attachments. Use these companions for field access, references, publication and final storage release.

The main boundaries

VFS, filesystems, and storage I/O diagram
VFS, filesystems, and storage I/O diagram · Open SVG
Mermaid source
flowchart TD
    SYS[BSD open/read/write/mmap] --> FD[fileproc / fileglob]
    SYS --> NAME[namei / lookup / name cache]
    NAME --> VN[vnode and filesystem vnode operations]
    FD --> VN
    VN --> AUTH[Vnode authorization / MAC checks]
    VN --> FS[Filesystem implementation]
    MOUNT[mount / VFS operations] --> FS
    FS --> UBC[UBC / VM object / clustered I/O]
    VM[VM fault and pageout] --> UBC
    UBC --> BUF[buf I/O descriptions]
    FS --> BUF
    BUF --> DEV[Device strategy / storage stack]
    NET[NFS server RPC] --> VN

The filesystem decides whether and how to use clustered I/O. A generic VNOP_READ wrapper does not automatically invoke the buffer cache, and a read can finish entirely from resident UBC pages. Device and network-backed objects take different routes.

Layer Principal source What to look for
Syscalls and open files vfs_syscalls.c, sys_generic.c, vfs_vnops.c Path-based setup, fileglob operations, shared offsets and stored credentials
Pathnames vfs_lookup.c, vfs_cache.c, nameidata Component lookup, mount/symlink traversal, positive and negative cache entries
Vnode lifecycle vnode, vfs_subr.c I/O references, persistent references, identity generations, inactive/reclaim
Mounts and registration mount, vfs_init.c, kpi_vfs.c Filesystem instance vs filesystem type; mount operations vs vnode operations
File contents ubc_info, ubc_subr.c, vfs_cluster.c File VM object, UPLs, read-ahead, write-behind, extent mapping
Buffer/device I/O buf, vfs_bio.c, spec_vnops.c Buffer ownership, submission, completion and device-switch dispatch
Remote requests nfs_syscalls.c, nfs_socket.c, nfs_serv.c NFS server requests translated into local VFS operations

What this tree contains

The checkout supplies the generic VFS infrastructure and small filesystems/layers under bsd/miscfs. It does not supply the APFS filesystem implementation or a complete physical storage-driver stack. Calls through registered vfsops, vnode operation vectors and block/character device switches cross those boundaries. The presence of APFS-specific integration or ioctl names elsewhere in XNU does not expose APFS's allocation, transaction or on-disk algorithms.

Likewise, the available bsd/nfs implementation is chiefly the NFS server, RPC and GSS support. There is no client nfs_vfsops.c or nfs_vnops.c here. nfs_register_hooks exposes integration hooks for externally supplied behavior. The final chapter distinguishes what can actually be traced from this checkout from those missing implementations.

Useful reading routes

These are reading routes, not exhaustive call graphs: compound operations, retries, cached fast paths and configuration branches alter the sequence.

Sources inspected and limits

“Deep” means the named structures and selected multi-stage paths were read; it does not mean every branch of these large files was audited.

Area Inspection Coverage and limits
Vnode/mount/open-file model Deep structure definitions and selected reference/drain/inactive/clean/reclaim code in vnode_internal.h, mount_internal.h, file_internal.h, vnode.h, vfs_subr.c Allocation holds versus I/O/use references and identity; drain admission variants, callback lock release, dead-state installation and reuse ordering; not every revoke/reference race
Open/read/write and namespace dispatch Deep selected vfs_syscalls.c, vfs_vnops.c, vfs_subr.c, sys_generic.c, kpi_vfs.c Create/mkdir/link/unlink/rename authorization, compound continuation, lock/relookup/retry and cleanup; read/offset/credential/vector paths; not every ioctl, fcntl, event or metadata syscall
Lookup and authorization Deep nameidata/cache structures, component/mount/symlink handling, SMR and locked cache lookup, publication counters, generation-checked insertion, invalidation, open/search authorization; local ACL ordering, residual POSIX checks, deletion and creation inheritance Common route, negative entries, reference conversion and retry; external filesystem storage, membership-service databases, complete named-stream and MAC-provider behavior remain boundaries
UBC/cluster/buffer I/O Deep UBC/pager/object lifetime, resident-copy and missing-page reads, read-ahead decisions, mapping/last-unmap, size/truncation and invalidation; buffer hash/busy/free/storage/GC state; write classification/copy/zeroing, dirty tracking, UPL gathering, strategy transactions and completion File-page and buffer-header/storage caches kept separate; complete vector-UPL internals, external filesystem/verification providers and every throttling/read-ahead combination remain narrower
Mount lifecycle, boot and registration Deep selected root mount, mount_common publication/rollback, lookup_traverse_mountpoints, vfs_busy, dounmount, vflush, reference drains, filesystem registration and operation vectors Mount failure and force/device branches included; product-specific root-volume policy and every nested-mount/trigger race are not fully traced
Small filesystems and special nodes Deep selected devfs registration/lookup/clone/refcount/mount lifecycle, specfs alias/open/data/close dispatch, FIFO activation/peer/close, bindfs/nullfs alias hash/lookup/synthetic namespace/context/page-in/unmount Four concrete lifecycle implementations; routefs and mockfs remain surveys, not a complete audit of every filesystem
NFS Deep selected socket/upcall/framing/parser/worker ownership, replay cache, file-handle/mount/credential conversion, READ/WRITE/gather/COMMIT and shutdown; existing fhopen, GSS and registration-hook survey Current NFSv2/v3 server paths and limits; no complete RPC/security audit and no absent NFS client implementation inferred
Metadata, locks and events Attribute packing/bulk progress/set ordering, native and DoubleAgent xattrs, lockf ranges/waiters/close, lease breaks, event watcher publication/delivery/loss/close External filesystem metadata storage and DoubleAgent service bodies remain boundaries
Compressed files and quota infrastructure decmpfs header/provider/UBC/UPL/conversion paths, quota cache identity/refcounts/disk records/writeback Most codecs, APFS methods and filesystem quota charging are external; generic callbacks do not reveal those implementations

Useful adjacent originals are the VM pageout description and startup description. The devfs README explicitly identifies itself as inherited FreeBSD 3.1 commentary: use current source, rather than that historical feature list, for this version's behavior.

Search the handbook

Search every chapter, interface and code excerpt.

    Diagram

    Source preview

    Open full file