· 6 min read ·

What a Vibe-Coded ext4 Driver Reveals About AI-Assisted Kernel Work

Source: lobsters

The combination of “vibe coding” and “OpenBSD kernel” in the same sentence signals something worth paying attention to. OpenBSD is the project that ships a complete operating system rather than just a kernel, has a multi-decade record of proactive security work, and treats every new line of kernel code as a potential liability. Vibe coding, as Andrej Karpathy framed it in February 2025, is the practice of accepting LLM output with minimal line-by-line scrutiny, letting the feedback loop of compile-run-observe drive iteration rather than careful reading. Applying that methodology to a kernel filesystem driver is exactly the kind of collision that produces interesting data about both subjects.

The LWN article documents someone building a read-only ext4 driver for OpenBSD using this approach. OpenBSD has never shipped ext4 support in its base tree. If you plug a Linux disk formatted with ext4 into an OpenBSD system, nothing mounts. The gap has existed for decades; the project simply never prioritized it. So beyond the AI methodology angle, this is a genuine piece of missing infrastructure, which gives the experiment a clear success criterion: does it mount an ext4 volume and return correct file data.

What ext4 requires you to understand

The ext4 on-disk format is well-documented. The Linux kernel’s Documentation/filesystems/ext4/ covers the superblock layout, block group descriptor table, inode structure, and extent tree in detail. The magic number is 0xEF53, the superblock lives at offset 1024 bytes from the partition start, and a correct implementation must check the s_feature_incompat flags before mounting to determine whether it understands what it is looking at.

The part that makes ext4 significantly more complex than ext2 or ext3 is the extent tree. ext2 and ext3 use a simple indirect block pointer scheme: an inode has 12 direct block pointers, a single-indirect pointer, a double-indirect pointer, and a triple-indirect pointer. ext4 replaces this with a B-tree of extents, where each extent describes a contiguous run of logical-to-physical block mappings. The inode’s 60-byte i_block field stores up to three extent entries inline (the leaf case), or stores an extent index node header pointing to further index nodes. A correct read implementation must walk this tree to map a file offset to a physical block number, handling both the leaf and interior node cases.

Feature flags determine what a read-only driver can safely ignore. The key incompatible features are EXT4_FEATURE_INCOMPAT_EXTENTS (required for any modern ext4 volume), EXT4_FEATURE_INCOMPAT_64BIT (for volumes with more blocks than fit in 32 bits), and EXT4_FEATURE_INCOMPAT_FILETYPE (file type stored in directory entries, which simplifies lookup). Critically, if EXT4_FEATURE_INCOMPAT_RECOVER is set, the journal contains uncommitted data and a read-only driver must refuse to mount entirely. Presenting dirty journal state as ground truth means reading stale or partially-written data without any indication something is wrong.

Directory entries are variable-length records: an inode number, a record length, a name length byte, a file type byte, and the entry name. Reading a directory means walking these records until the sum of lengths reaches the block size, then moving to the next directory block. Large directories may use an htree index, a hash-tree structure for O(log n) lookup, but a read-only driver can ignore the index and fall back to linear scan without correctness problems.

BSD VFS and what it demands

OpenBSD’s Virtual File System layer descends from 4.4BSD’s VFS. A filesystem driver registers two tables of function pointers: a vfsops struct covering volume-level operations (mount, unmount, root, statfs, sync, vget) and a vnodeops struct covering per-file operations (lookup, read, getattr, readdir, readlink, inactive, reclaim, and several others). For a read-only driver, write-side operations return EROFS; the minimum viable set for useful operation is a handful of read and lifecycle callbacks.

The boilerplate shape of this is legible from existing in-tree drivers. sys/msdosfs/ in OpenBSD’s source tree provides a reference for a non-UFS read-write driver; the field names, calling conventions, and error return patterns are consistent across drivers. FreeBSD has shipped ext2/ext3 support in sys/fs/ext2fs/ since the early 2.x era, with ext4 extent tree read support added later, giving any LLM trained on open-source BSD code direct exposure to what a BSD ext filesystem driver looks like. NetBSD has a driver in the same lineage.

Where the LLM helps and where it stops

The mechanical parts of this project are genuinely well-suited to LLM assistance. Translating the struct ext4_super_block layout into an OpenBSD-style C header, writing the superblock validation logic, implementing the extent tree traversal from the documented algorithm, parsing directory entry records: these are tasks the model can approach with high accuracy because the source material is explicit and the expected output is narrow. The LLM has seen both the ext4 specification and multiple BSD filesystem drivers during training; the task of combining them is closer to translation than invention.

Where it becomes unreliable is in the cross-cutting concerns that kernel code accumulates through decades of concurrent use. BSD kernels use a layered locking model where the kernel lock, vnode locks, and buffer locks interact in specific sequences that differ between operations. Getting lookup to acquire and release the vnode lock in the right sequence matters not just for correctness but for deadlock avoidance. The reclaim vnode callback must release all resources associated with a vnode exactly once, under specific conditions, because over-release causes a panic and under-release accumulates into a leak.

Endianness is another pressure point. ext4 is little-endian. OpenBSD runs on amd64 and arm64 but also on several historically big-endian architectures. The correct approach is to apply letoh32() and letoh64() to every field read from disk. An LLM generating code in an amd64-centric context will often produce code that works on amd64 and silently misreads block numbers on big-endian hardware, because the machine the model implicitly assumes matches the architecture where most testing occurs.

Error paths are a third problem. A correct mount routine that fails partway through must release every resource allocated before the failure. If block group descriptors were allocated but the inode table read fails, the error path must free the group descriptors before returning. LLM-generated error paths frequently omit cleanup for early allocations, because the model generates code sequentially and the early allocation is no longer in the immediate window by the time it writes the error handler. These bugs do not cause panics in the happy path; they surface as slow memory leaks or as panics triggered by specific unmount sequences.

The OpenBSD context

OpenBSD’s approach to new kernel code is conservative in a principled way. More code means more attack surface; a filesystem driver that processes attacker-controlled on-disk data is a meaningful addition to the security perimeter. The project has historically declined to add drivers it considers unnecessary for its security-focused use case, which explains the ext4 gap.

That framing makes the vibe coding methodology particularly interesting here. A driver whose author cannot fully explain every concurrency decision, written in a feedback-loop style that prioritizes observed behavior over code comprehension, is not going to land in the OpenBSD base tree. But the project is not claiming to be that. A personal tool for reading Linux disks on an OpenBSD workstation is a different thing from a production driver with upstream ambitions, and the read-only constraint is doing significant work in that distinction. A read-only driver’s worst-case failure is returning wrong data or panicking; it cannot corrupt the filesystem it is reading. That asymmetry matters when evaluating AI-generated code in a high-stakes domain: the blast radius is bounded by the refusal to write.

What this maps out

The project is useful not because it produces something ready for the OpenBSD base tree, but because it delineates where current models are genuinely helpful and where their output requires careful review before it is trustworthy. The structural and algorithmic layer, parsing on-disk formats, implementing documented algorithms, wiring up VFS scaffolding, maps onto what LLMs do well: pattern matching against large training corpora of similar code, mechanical translation between representations, filling in boilerplate that follows clear conventions. The concurrency model, vnode lifecycle management, error path correctness, and cross-platform portability fall outside that, because the relevant knowledge is distributed across dozens of interacting call sites rather than localized in a single function the model can see at once.

The read-only ext4 case is tractable for an LLM-assisted approach in a way that a read-write driver probably is not. Write path correctness in a journaling filesystem requires understanding the ordering guarantees between journal commits, data writes, and metadata updates, a kind of global reasoning that does not reduce to implementing a documented algorithm from a specification. That distinction, between the locally specifiable and the globally constrained, is a cleaner boundary for AI-assisted systems work than the surface-level distinction between “easy” and “hard” code.

Was this interesting?