Understanding GEOM: FreeBSD's Modular Storage Framework
How GEOM's graph of providers and consumers underlies partitioning, RAID, encryption, and disk labels on FreeBSD.
Every time you partition a disk, mirror two drives, or encrypt a volume on FreeBSD, you’re using GEOM, the kernel framework that models storage as a directed graph of interchangeable modules. Where many operating systems bolt RAID, encryption, and partitioning on as separate, only-loosely-related subsystems, FreeBSD implements all of them as GEOM classes speaking the same protocol — which is why they compose so cleanly with each other.
Providers and consumers
GEOM’s vocabulary has exactly two building blocks. A provider is anything that offers a block-storage interface — a raw disk, a partition, a mirrored volume. A consumer is anything that attaches to a provider to use it — a filesystem, another GEOM class building a new provider on top. A GEOM class like MIRROR or ELI (encryption) is simultaneously a consumer of its underlying disks and a provider of the new, transformed device it exposes.
# Visualize the current GEOM graph
geom -h
gpart show
geom mirror list
This graph structure is why GEOM classes stack: gmirror can sit on top of raw disks, geli (encryption) can sit on top of the mirror, and UFS or ZFS can sit on top of the encrypted device — each layer only aware of the provider directly beneath it.
UFS → geli (encryption) → gmirror (RAID1) → ada0, ada1
GPT partitioning: gpart
gpart is the GEOM class most people interact with first, whether they realize it or not — it’s what creates and manages GPT (or legacy MBR) partition tables:
gpart create -s gpt ada0
gpart add -t freebsd-boot -s 512K ada0
gpart add -t freebsd-zfs -l disk0 ada0
gpart show ada0
The -l flag assigns a label, which is itself exposed as a new GEOM provider (gpt/disk0) — meaning you can reference the partition by its stable label rather than the device node name, which can shift if disks are re-enumerated after a hardware change.
Software RAID: gmirror, gstripe, graid3
gmirror implements RAID1, gstripe implements RAID0, and graid3 implements a dedicated-parity-disk RAID3 — all as GEOM classes with essentially the same command shape:
gmirror label -v data ada1 ada2
mount /dev/mirror/data /mnt
# Simulate a failed disk and observe GEOM's degraded-mode handling
gmirror forget data
gmirror insert data ada3
Because these are kernel-level GEOM classes rather than userland software RAID, the resulting /dev/mirror/data provider behaves like any other disk device to everything above it — newfs, zpool create, or a raw dd all just work without needing RAID-awareness.
Encryption: geli
geli provides full-disk (or full-partition) encryption as another GEOM transform, sitting between the raw provider and whatever consumes it:
geli init -s 4096 /dev/da0p3
geli attach /dev/da0p3
newfs /dev/da0p3.eli
mount /dev/da0p3.eli /mnt
The .eli suffix on the resulting device name is GEOM’s convention for a transformed provider — the same pattern gmirror and gpart use (mirror/data, da0p1), reflecting that these are all just nodes in the same graph, named according to which class produced them.
Journaling: gjournal
gjournal adds UFS journaling by inserting a GEOM layer that logs metadata (and optionally data) updates before they’re committed to the underlying provider, allowing fast, consistent recovery after an unclean shutdown — a role ZFS makes largely unnecessary via its own copy-on-write design, but still relevant for UFS-based systems.
Why the layered model matters
The practical payoff of GEOM’s uniform provider/consumer model is that these classes require no special-casing to combine — gmirror doesn’t need to know anything about geli, and gpart doesn’t need to know anything about either. Each class solves exactly one problem and exposes a plain block device to whatever sits above it. When troubleshooting a storage stack that layers several of these, geom <class> list and gpart show at each layer let you walk the graph directly, confirming exactly which provider is misbehaving instead of treating the whole storage stack as one opaque unit.