Uberblok, un museo de OpenZFS donde cada sala cita el código
Uberblok es un museo interactivo sobre OpenZFS en 14 etapas: cada afirmación técnica remite a las líneas exactas de zfs-2.4.4. Lo construyeron agentes; yo fijé la misión.
Uberblok está en línea: un museo sobre OpenZFS que se visita sala por sala. Catorce etapas: un vestíbulo, un ala dedicada a la historia, once salas técnicas y una sala de máquinas. Cada afirmación técnica remite a un extracto anotado del código de OpenZFS zfs-2.4.4, fijado en el commit 71a9f95. Cada hecho del ala Historia tiene su línea en SOURCES.md.
Lo construyeron agentes de IA, entre el 18 y el 20 de octubre. Yo escribí la misión, di mi opinión sobre cada versión y validé la puesta en línea. La sala de máquinas del sitio lo dice en una frase: «El sitio lo escribieron agentes de IA, a partir de una misión fijada por una persona que valida la publicación».
# Por qué ZFS
ZFS ha contado mucho en mi carrera. De 2010 a 2018 fui responsable técnico del almacenamiento de archivos en OVHcloud. La robustez de ZFS nos impresionó en cuanto lo probamos, como otras tecnologías vanguardistas de Sun, de Solaris y luego de OpenSolaris: las Zones o Crossbow. Sobre esa base construimos productos realmente potentes, hasta sistemas de alta disponibilidad que conmutan de una cabeza a otra en caso de fallo, y send/receive muy optimizados, con mbuffer y compresión. Desplegado a gran escala, ZFS es una delicia.
Las ganas de rendirle homenaje llegaron solas: sumergirme en las entrañas de su código, que es una magnífica pieza de ingeniería de software.
# Lo que quería
La misión cabía en una frase: « 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 » [un museo que se visita sala por sala, donde cada sala hace visible […] una idea de ingeniería del código fuente de OpenZFS]. La acompañaban dos reglas. Para las salas: « Une animation qui ne correspond à rien dans le code n’existe pas. » [Una animación que no corresponde a nada en el código no existe.] Para la historia: « Aucun fait, aucune date, aucune citation sans source vérifiable. Dans le doute, on retire. » [Ningún hecho, ninguna fecha, ninguna cita sin fuente verificable. Ante la duda, se quita.]
Así que el código pasó antes que las figuras. Un primer archivo, ANALYSIS.md, cartografía la arquitectura y, para cada sala, las funciones y estructuras que sostienen la idea. Hoy contiene 116 extractos. Las páginas los leen al compilarse, y un script comprueba que cada uno es idéntico, byte a byte, al archivo del commit fijado. La mayoría de las figuras ejecutan una transcripción del código que muestran, probada con casos calculados a mano. El ala Historia se apoya en 43 fuentes, y la CI comprueba que cada nota del sitio corresponde a una línea de SOURCES.md.
# Donde se rompió
El primer error venía de mi propia misión. En ella describía el objeto del vestíbulo como « l’uberblock et son ring de 128 » [el uberblock y su ring de 128]. El código dice otra cosa: el ring ocupa 128 KiB por label, y el tamaño de cada ranura depende del ashift del disco (vdev_impl.h, L482 a L496). Hay 128 ranuras con sectores de 512 bytes, pero solo 32 con ashift 12, el caso habitual de los discos con sectores de 4 KiB.
Se sopesaron tres opciones. Escribir «128 uberblocks» sin matices era falso para la mayoría de los pools en servicio. Mostrar solo 32 era exacto, pero perdía la imagen de partida. La elección: un ring de 128 KiB, dibujado con 128 ranuras, y un selector de ashift que las fusiona en 64, 32 o 16. El vestíbulo sigue fiel al código, y la imagen de la misión se conserva.
ashift 9 o 10): 128 ranuras de 1 KiB. El uberblock del txg 4211 ocupa la ranura 115, porque 4211 módulo 128 es 115; el del txg 4210 sigue intacto justo antes.
El segundo lo detectó la revisión de código de un tramo. Una nota de la sala send / receive afirmaba que la deduplicación y la clonación de bloques no provocan el reenvío de datos sin cambios. El comentario de spa.h que citaba dice lo contrario: para esos bloques, el nacimiento físico puede ser anterior al nacimiento lógico. Como send se basa en el nacimiento lógico, un bloque deduplicado o clonado después del snapshot de partida sí se reenvía. La nota se corrigió, en la página y en ANALYSIS.md.
# La sala que más hace trabajar las neuronas
Para mí, es Metaslabs y space maps. ¡Los metaslabs son algo serio! Una revolución de software de la que poca gente es consciente.
El problema de partida, tal como lo plantea la sala: con la copia en escritura, cada escritura asigna espacio nuevo, y el espacio libre debe anotarse en el disco. Un bitmap de un pool de 16 TiB, a un bit por sector de 4 KiB, pesaría 512 MiB y habría que modificarlo in situ, cosa que la copia en escritura prohíbe. En su lugar, ZFS divide cada vdev en metaslabs, unos 200 por defecto, guarda el espacio libre de cada uno en un árbol en memoria y solo escribe en el disco los cambios, en un space map al que solo se añade. Cuando se vuelve demasiado largo, lo reescribe más corto a partir del árbol.
En la figura, el space map de un metaslab de 512 MiB es una banda de palabras de 64 bits, codificadas como lo hacen las macros de space_map.h. Reescribiendo una base de datos de 64 MiB hasta que la prueba de condensación dice que sí, el map pasa de 66 432 a 3376 bytes.
# Dónde estoy
¡Mi mente aún no ha asimilado todo lo que se ha generado! Es lo que me impresiona de este proyecto: me enseña cosas mientras lo construyo. Probablemente una vida no bastará para entender todas las sutilezas de ZFS.
El criterio de éxito de la misión era: « si Matt Ahrens ou Jeff Bonwick tombaient dessus, ils trouveraient l’exposé exact, élégant, et fidèle au code » [si Matt Ahrens o Jeff Bonwick dieran con él, encontrarían la exposición exacta, elegante y fiel al código]. No tengo las competencias para decir si se cumple. Si alguno de ellos llega un día al sitio, solo espero que no encuentre demasiadas erratas. Y que disfrute desmenuzándolo tanto como yo.
El museo está en línea; su código, ANALYSIS.md, DECISIONS.md y BUILDLOG.md están en el repositorio público.