<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>storagebits · #zfs</title>
    <subtitle>Firmware, TV apps, a homelab, built at night with an organization of AI agents. And blok, the workshop notebook.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blok.storagebits.workers.dev/tags/zfs/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blok.storagebits.workers.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-20T18:22:20-04:00</updated>
    <id>https://blok.storagebits.workers.dev/tags/zfs/atom.xml</id>
    <entry xml:lang="en">
        <title>Uberblok, an OpenZFS museum where every room cites the code</title>
        <published>2026-10-20T18:22:20-04:00</published>
        <updated>2026-10-20T18:22:20-04:00</updated>
        <author><name>François</name></author>
        <link rel="alternate" type="text/html" href="https://blok.storagebits.workers.dev/blog/uberblok/"/>
        <id>https://blok.storagebits.workers.dev/blog/uberblok/</id>
        <summary type="html">Uberblok is an interactive museum about OpenZFS in 14 stops: every technical claim points to the exact lines of zfs-2.4.4. Agents built it; I set the mission.</summary>
        <content type="html" xml:base="https://blok.storagebits.workers.dev/blog/uberblok/">&lt;p&gt;&lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://uberblok.storagebits.workers.dev/en/&quot;&gt;Uberblok&lt;/a&gt; is live: a museum about OpenZFS that you visit room by room. Fourteen stops: a hall, a wing devoted to history, eleven technical rooms and an engine room. Every technical claim points to an annotated excerpt of the OpenZFS code at &lt;code&gt;zfs-2.4.4&lt;/code&gt;, pinned at commit &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://github.com/openzfs/zfs/tree/71a9f9578616a90c3c14bb59629fb4d31bfd68d1&quot;&gt;&lt;code&gt;71a9f95&lt;/code&gt;&lt;/a&gt;. Every fact in the &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://uberblok.storagebits.workers.dev/en/history/&quot;&gt;History wing&lt;/a&gt; has its line in &lt;code&gt;SOURCES.md&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;AI agents built it, between October 18 and 20. I wrote the mission, gave my opinion on every version and approved the release. The site’s &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://uberblok.storagebits.workers.dev/en/engine-room/&quot;&gt;engine room&lt;/a&gt; says it in one sentence: “The site was written by AI agents, from a mission set by a human who validates the release.”&lt;/p&gt;
&lt;h2 id=&quot;why-zfs&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-zfs&quot; aria-label=&quot;Anchor link for: why-zfs&quot;&gt;#&lt;/a&gt;
Why ZFS&lt;/h2&gt;
&lt;p&gt;ZFS mattered a lot in my career. From 2010 to 2018, I was technical lead for file storage at OVHcloud. ZFS’s robustness impressed us as soon as we tried it, like other forward-looking technologies from Sun, Solaris and then OpenSolaris: Zones, or Crossbow. On that foundation we built really powerful products, up to high-availability systems that fail over from one head to the other, and heavily optimized send/receive, with mbuffer and compression. Deployed at scale, ZFS is a joy.&lt;/p&gt;
&lt;p&gt;The wish to pay tribute to it came naturally: diving into the guts of its code, which is a magnificent piece of software engineering.&lt;/p&gt;
&lt;h2 id=&quot;what-i-wanted&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-wanted&quot; aria-label=&quot;Anchor link for: what-i-wanted&quot;&gt;#&lt;/a&gt;
What I wanted&lt;/h2&gt;
&lt;p&gt;The mission fit in one sentence: « un musée que l’on visite salle par salle, où chaque salle rend visible […] une idée d’ingénierie du code source d’OpenZFS » [a museum you visit room by room, where each room makes visible […] an engineering idea from the OpenZFS source code]. Two rules came with it. For the rooms: « Une animation qui ne correspond à rien dans le code n’existe pas. » [An animation that matches nothing in the code does not exist.] For history: « Aucun fait, aucune date, aucune citation sans source vérifiable. Dans le doute, on retire. » [No fact, no date, no quote without a verifiable source. When in doubt, cut it.]&lt;/p&gt;
&lt;p&gt;So the code came before the figures. A first file, &lt;code&gt;ANALYSIS.md&lt;/code&gt;, maps the architecture and, for each room, the functions and structures that carry the idea. It now holds 116 excerpts. The pages read them at build time, and a script checks that each one is identical, byte for byte, to the file at the pinned commit. Most figures run a transcription of the code they show, tested against cases worked out by hand. The History wing rests on 43 sources, and CI checks that every note on the site matches a line in &lt;code&gt;SOURCES.md&lt;/code&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;copie-sur-ecriture.png&quot; alt=&quot;The figure in the copy-on-write room: a tree of blocks, from the uberblock (UB, txg 41) down to four data blocks, with buttons to pick a block, rewrite it step by step, cut the power or take a snapshot.&quot; width=&quot;1112&quot; height=&quot;505&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;The &lt;a href=&quot;https://uberblok.storagebits.workers.dev/en/copy-on-write/&quot;&gt;copy-on-write room&lt;/a&gt;: each block carries the txg that wrote it and its address on disk. You rewrite a block step by step, and you can cut the power at any step.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;where-it-broke&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-it-broke&quot; aria-label=&quot;Anchor link for: where-it-broke&quot;&gt;#&lt;/a&gt;
Where it broke&lt;/h2&gt;
&lt;p&gt;The first mistake came from my own mission. In it, I described the object in the hall as « l’uberblock et son ring de 128 » [the uberblock and its ring of 128]. The code says otherwise: the ring takes 128 KiB per label, and the size of a slot depends on the disk’s &lt;code&gt;ashift&lt;/code&gt; (&lt;code&gt;vdev_impl.h&lt;/code&gt;, L482 to L496). There are 128 slots with 512-byte sectors, but only 32 at &lt;code&gt;ashift&lt;/code&gt; 12, the usual case for disks with 4 KiB sectors.&lt;/p&gt;
&lt;p&gt;Three options were weighed. Writing “128 uberblocks” with no caveat was wrong for most pools in service. Showing only 32 was accurate, but lost the original picture. The choice: a 128 KiB ring, drawn with 128 slots, and an &lt;code&gt;ashift&lt;/code&gt; selector that merges them into 64, 32 or 16. The &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://uberblok.storagebits.workers.dev/en/&quot;&gt;hall&lt;/a&gt; stays true to the code, and the mission’s picture is kept.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;anneau-en.png&quot; alt=&quot;The hall&#39;s ring in 3D view: a ring of 128 slots, with &quot;txg 4211, slot 115 of 128&quot; in the middle. Slot 115 is orange, slot 114 light grey.&quot; width=&quot;780&quot; height=&quot;500&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;The hall&#39;s ring in 3D view, with 512-byte or 1 KiB sectors (&lt;code&gt;ashift&lt;/code&gt; 9 or 10): 128 slots of 1 KiB. The uberblock of txg 4211 sits in slot 115, because 4211 modulo 128 is 115; the one from txg 4210 stays intact just before it.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The second was caught by the code review of a slice. A note in the &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://uberblok.storagebits.workers.dev/en/send-receive/&quot;&gt;send / receive room&lt;/a&gt; claimed that deduplication and block cloning don’t cause unchanged data to be sent again. The &lt;code&gt;spa.h&lt;/code&gt; comment it cited says the opposite: for those blocks, the physical birth can be earlier than the logical birth. Since send relies on the logical birth, a block deduplicated or cloned after the starting snapshot is sent again. The note was fixed, on the page and in &lt;code&gt;ANALYSIS.md&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-room-that-works-the-brain-hardest&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-room-that-works-the-brain-hardest&quot; aria-label=&quot;Anchor link for: the-room-that-works-the-brain-hardest&quot;&gt;#&lt;/a&gt;
The room that works the brain hardest&lt;/h2&gt;
&lt;p&gt;For me, it’s &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://uberblok.storagebits.workers.dev/en/metaslabs/&quot;&gt;Metaslabs and space maps&lt;/a&gt;. Metaslabs are really something! A software revolution few people are aware of.&lt;/p&gt;
&lt;p&gt;The starting problem, as the room puts it: with copy-on-write, every write allocates fresh space, and free space has to be recorded on disk. A bitmap for a 16 TiB pool, one bit per 4 KiB sector, would weigh 512 MiB and would have to be modified in place, which copy-on-write forbids. Instead, ZFS cuts each vdev into metaslabs, about 200 by default, keeps each one’s free space in an in-memory tree and writes only the changes to disk, in a space map that is only ever appended to. When it grows too long, it rewrites it shorter from the tree.&lt;/p&gt;
&lt;p&gt;In the figure, the space map of a 512 MiB metaslab is a strip of 64-bit words, encoded the way the macros in &lt;code&gt;space_map.h&lt;/code&gt; do it. Rewriting a 64 MiB database until the condensing test says yes, the map shrinks from 66,432 to 3,376 bytes.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;metaslabs-en.png&quot; alt=&quot;The figure in the Metaslabs room: the 16 metaslabs of an 8 GiB vdev, the strip of metaslab 2 streaked with freed segments, the in-memory state (ms_allocatable: 380 MiB in 225 segments) and the space map on disk, 37,392 bytes long, made mostly of FREE entries of 128 and 256 KiB.&quot; width=&quot;2144&quot; height=&quot;1684&quot; loading=&quot;lazy&quot;&gt;&lt;figcaption&gt;The Metaslabs room after 40 txgs of rewriting the 64 MiB database: the free space of metaslab 2 is split into 225 segments, and its space map reaches 37,392 bytes, mostly FREE entries. It is not yet long enough to be condensed.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;where-i-am&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-i-am&quot; aria-label=&quot;Anchor link for: where-i-am&quot;&gt;#&lt;/a&gt;
Where I am&lt;/h2&gt;
&lt;p&gt;My mind hasn’t yet taken in everything that was generated! That’s what impresses me about this project: it teaches me things while I build it. A lifetime probably won’t be enough to understand all the subtleties of ZFS.&lt;/p&gt;
&lt;p&gt;The mission’s success criterion was: « si Matt Ahrens ou Jeff Bonwick tombaient dessus, ils trouveraient l’exposé exact, élégant, et fidèle au code » [if Matt Ahrens or Jeff Bonwick stumbled on it, they would find the explanation accurate, elegant, and true to the code]. I don’t have the skills to say whether it’s met. If one of them ever lands on the site, I only hope he won’t find too many typos. And that he’ll enjoy taking it apart as much as I do.&lt;/p&gt;
&lt;p&gt;The &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://uberblok.storagebits.workers.dev/en/&quot;&gt;museum&lt;/a&gt; is live; its code, &lt;code&gt;ANALYSIS.md&lt;/code&gt;, &lt;code&gt;DECISIONS.md&lt;/code&gt; and &lt;code&gt;BUILDLOG.md&lt;/code&gt; are in the &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://github.com/algotitanhq/uberblok&quot;&gt;public repository&lt;/a&gt;.&lt;/p&gt;
&lt;aside class=&quot;transparence&quot; aria-label=&quot;How this post was written&quot;&gt;
  &lt;p class=&quot;transparence-titre&quot;&gt;How this post was written&lt;/p&gt;
  &lt;p&gt;Drafted by Claude Opus 5.5 from: a mission prompt and an interview written by François, the public &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://github.com/algotitanhq/uberblok&quot;&gt;&lt;code&gt;uberblok&lt;/code&gt;&lt;/a&gt; repository (&lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;BUILDLOG.md&lt;/code&gt;, &lt;code&gt;DECISIONS.md&lt;/code&gt;, &lt;code&gt;SOURCES.md&lt;/code&gt;) and the live site.&lt;/p&gt;
  &lt;p&gt;Proofread and corrected by François in 30 min, 2 % of the text rewritten.&lt;/p&gt;
  &lt;p&gt;Translated from French by the AI, from the proofread version. The translation was not reviewed line by line.&lt;/p&gt;
&lt;/aside&gt;
</content>
    </entry>
</feed>
