Linux kernel design patterns - part 3 (Precis)
Neil Brown concludes his three-part series on design patterns in the Linux kernel by focusing on one pattern — the "midlayer mistake" — and then summarizing all ten patterns discovered across the series. The midlayer mistake is both a pattern and an anti-pattern: it describes how midlayers (code sitting between a generic top layer and specific bottom-layer drivers) tend to go wrong, and prescribes a library-based alternative.
The core thesis: midlayers are bad and should not exist. Common functionality should be provided as a library that bottom-level drivers can use, augment, or ignore — rather than a midlayer imposed on every driver. Brown identifies four tell-tale signs of a midlayer: (1) code being imposed on lower layers, (2) special cases accumulating in that code, (3) data structures storing pointers to subordinate data structures (instead of using the embedded anchor pattern), and (4) unrelated code being called by one support function.
Three kernel subsystems are examined through this lens. The block layer elevator was once a true midlayer but has moved toward a library model via blk_queue_make_request(), though it still retains midlayer artifacts like the struct request_queue mixing elevator fields with block-interface fields. The VFS is a shining example of getting it right: thin vfs_ functions call directly into filesystem-specific _operations structures, and the page cache provides an exemplary library that ext3 uses for 8 of its 13 file operations — while the dcache is a counter-example, imposed on every filesystem including those (network, virtual) that don't benefit from its services. The MD/RAID layer is a mess: historical major-number constraints forced a midlayer mentality that persists today, with library-like functions (md_register_thread()) undermined by midlayer behavior (md unregistering threads it didn't create).
The series summary lists all ten patterns: kref, kcref, plain ref (three reference-counting patterns), biased-reference (anti-pattern), embedded anchor, broad interfaces, tool box, caller locks, preallocate outside locks, and midlayer mistake. Brown closes by arguing a compiled collection of kernel design patterns would improve visibility at the design level and raise code quality.