This page provides a technical exploration of the XFS filesystem's internal infrastructure for buffer management (xfs_buf), zone-aware allocation and garbage collection for zoned block devices, mount/superblock lifecycle, and the integrated health monitoring and error reporting systems.
XFS manages metadata buffers using specialized buffer objects called xfs_buf, which encapsulate the metadata pages and provide extended control beyond standard Linux buffer heads. This design allows fine-grained management including transaction integration, concurrency control, and metadata verification.
Buffers are primarily managed with a cache xfs_buf_cache keyed by device and block number, implemented as a per-target rhashtable (bt_hash). When a buffer is requested, the lookup occurs in this rhashtable to find an existing buffer; on cache miss, a new buffer is allocated.
Buffer Allocation Strategy:
Based on buffer size and memory alignment:
Small buffers (< PAGE_SIZE): allocated using kmalloc to avoid wasting a full page.
Buffers fitting exactly into a folio (usually PAGE_SIZE or multiples): use folio_alloc(), which allocates a contiguous set of pages efficiently backed by the Linux folio abstraction.
Larger or discontiguous buffers: allocated via vmalloc(), which provides non-contiguous physical memory mapped into a contiguous virtual address space.
This tiered allocator strategy balances memory efficiency and performance.
Buffer Mapping:
The buffer may map to either:
Contiguous physical pages (folio_address()), or
vmalloc’ed virtual memory.
Buffer Flags:
Buffers have internal flags indicating their allocation type:
_XBF_KMEM for kmalloc buffers,
_XBF_FOLIO for folio buffers,
_XBF_VMALLOC for vmalloc buffers.
The allocator sets and uses these flags during allocation and freeing.
xfs_buftarg)Buffers are grouped under xfs_buftarg structures representing block devices. Each xfs_buftarg tracks:
The underlying device,
A per-device buffer hash (bt_hash) of its buffers,
Least Recently Used (LRU) lists for reclaiming buffers deemed inactive,
Hardware constraints like Atomic Write Unit size, which affects buffer alignment and I/O sizing.
The main path for buffer retrieval and allocation is:
xfs_buf_read_map() initiates a buffer read.
This calls xfs_buf_get_map() to obtain or create the buffer.
xfs_buf_find() looks up the buffer in the rhashtable.
On miss, xfs_buf_alloc() creates a new buffer struct, invoking xfs_buf_alloc_backing_mem() for backing memory allocation.
The backing memory allocator chooses kmalloc/folio_alloc/vmalloc based on requested size.
References: The buffer management implementation is primarily in fs/xfs/xfs_buf.c and the buffer structures and flags are defined in fs/xfs/xfs_buf.h.
XFS supports zoned block devices, where device blocks are divided into zones requiring sequential writes (ZNS/SMR technology). To accommodate, XFS implements zone-aware allocation and garbage collection.
xfs_zone_info)Zones are tracked via xfs_zone_info attached to xfs_mount.
Zones are grouped into buckets based on usage:
Used blocks within each zone are quantified,
Zones are placed in buckets proportional to usage thresholds, facilitating quick search for zones with reclaimable space.
Transitioning Zones:
When a zone transitions from full to partial use, it is added to reclaimable buckets.
An empty zone triggers a reset process, queued in the reset list.
Locking:
Zone bucket updates are protected with spinlocks,
Reset list manipulations have separate spinlocks.
Wakeup triggers:
Due to sequential write constraints, XFS cannot simply overwrite data in a zone. GC moves live data from partially used zones to free zones:
The GC thread is triggered by xfs_zoned_need_gc() if:
There exist reclaimable zones with data,
Or if available free space is below configured thresholds.
The GC process:
Identifies victim zones to reclaim by scanning reverse mapping data structures.
Buffers valid extents into a scratchpad (set of allocated folios).
Writes these extents sequentially into a fresh target zone.
Updates file bmap btrees to remap extents to the new locations.
Marks the reclaimed zone as empty and queues it for device-level zone reset.
Key GC structures:
xfs_gc_bio: Represents I/O requests during GC for reads or writes.
xfs_zone_gc_data: Holds per-mount GC state, including scratchpad folios, I/O lists, and an iterator scanning mappings.
References: Zone allocation logic is found in fs/xfs/xfs_zone_alloc.c, and GC logic in fs/xfs/xfs_zone_gc.c.
XFS mount and superblock initialization integrate tightly with the VFS and are implemented using the modern fs_context API.
Mount options are parsed with xfs_fs_parameters fs/xfs/xfs_super.c124-179 defining known parameters such as:
Logging device (logdev), real-time device (rtdev).
Direct Access (dax) modes (inode, always, never).
Zoned storage limits (max_open_zones).
The superblock is read first with a minimal buffer to identify the sector size.
After sector size is confirmed, it is re-read with the correct size and buffer verifiers applied.
The superblock buffer head pointer is stored in mp->m_sb_bp.
Validation includes:
Verifying the magic number,
Checking UUID to prevent duplicate mounts.
UUID mount verification (xfs_uuid_mount()) ensures no UUID collision with other mounted filesystems.
Filesystem block counts are validated for device limitations and integrity using xfs_sb_validate_fsb_count().
References: Mount code and superblock handling in fs/xfs/xfs_super.c and fs/xfs/xfs_mount.c.
XFS provides an advanced health monitoring subsystem and error reporting infrastructure to improve reliability and diagnostics.
xfs_healthmon)The health monitor manages health event notifications to userspace monitoring daemons.
Events are merged to avoid spamming identical health conditions.
Functions:
xfs_healthmon_attach() and xfs_healthmon_detach() create and destroy monitor instances linked to mounts.
xfs_healthmon_merge_events() tries to combine redundant events for efficiency.
The health monitor manages a mutex-guarded list of active events.
Errors detected by internal verification layers or runtime operations are reported and tracked:
xfs_error_report() logs errors after filtering to avoid repetitive spam.
xfs_corruption_error() logs corruption-specific errors, generates hex dumps for debugging, and alerts to run xfs_repair.
Buffer metadata corruptions are reported via xfs_buf_corruption_error().
Quota corruption updates are handled via xfs_dquot_mark_sick() which tags the quota object as unhealthy and notifies health systems.
xfs_errortag allows developers to manually inject errors for testing error paths.
Error injection points include log I/O, metadata write failures, direct I/O errors, quota transactions.
Errors are enabled and configured via sysfs.
References: Error reporting system and health monitoring are implemented in fs/xfs/xfs_error.c, fs/xfs/xfs_healthmon.c, and quota corruption tracking in fs/xfs/xfs_dquot.c.
This page detailed the internal workings of XFS's:
Buffer caching: xfs_buf provides rich metadata buffer management with customized memory allocation and caching.
Zoned storage allocation: Advanced allocation and garbage collection manage sequentially written zones, supporting zoned block devices effectively.
Mount lifecycle: Superblock reading and validation with robust mount parameter handling ensure correctness.
Health monitoring and error reporting: Captures, merges, and reports filesystem events, helping diagnostics and active monitoring.
Buffer caching: fs/xfs/xfs_buf.c, fs/xfs/xfs_buf.h
Zoned allocation & GC: fs/xfs/xfs_zone_alloc.c, fs/xfs/xfs_zone_gc.c
Mount & superblock: fs/xfs/xfs_super.c, fs/xfs/xfs_mount.c
Health & error reporting: fs/xfs/xfs_error.c, fs/xfs/xfs_healthmon.c, fs/xfs/xfs_dquot.c
Buffer management: fs/xfs/xfs_buf.c1-320 fs/xfs/xfs_buf.h1-140
Zone allocation: fs/xfs/xfs_zone_alloc.c30-195 fs/xfs/xfs_zone_gc.c20-160
Mount & superblock lifecycle: fs/xfs/xfs_super.c61-180 fs/xfs/xfs_mount.c80-260
Health monitoring: fs/xfs/xfs_healthmon.c30-150
Error reporting: fs/xfs/xfs_error.c10-320 fs/xfs/xfs_dquot.c45-70
Refresh this wiki
This wiki was recently refreshed. Please wait 1 day to refresh again.