Bare-Metal Ada on the ESP32-S3 A step-by-step guide to running Ada on the ESP32-S3 with no ESP-IDF, no FreeRTOS, and no Python.

Step 47 of 56

ext4: a real filesystem, in Ada

A from-scratch ext2/3/4 implementation with JBD2 journal replay, an on-device formatter, and an error model that is simply Ada's.

Scope

ESP32S3.Ext4 is a reimplementation of lwext4 in pure Ada: read and write — create, write, truncate, mkdir, rmdir, unlink, rename, link — with metadata checksums and JBD2 journal replay. It is pure logic over Block_Dev, so it also compiles host-native and is developed against a harness that checks every operation against mke2fs, debugfs and e2fsck.

The pieces are separate children rather than one monolith: superblock, group descriptors, inodes, bitmaps, block map, block cache, directories, paths, files, the writer, the journal, mkfs, and a VFS layer that presents several mounted volumes as one tree.

The error model is Ada's

Operations raise rather than returning status codes, and the IO-family exceptions are the standard ones from Ada.IO_Exceptions — chosen so a future Ada.Streams.Stream_IO bridge maps cleanly — plus a few filesystem-specific additions. That is a deliberate departure from the Status-out-parameter style used by the bus drivers, and it is the right one here: a filesystem call has many more failure modes than a bus transaction, and threading them all through return values would drown the call sites.

Journal replay

The JBD2 journal lives in inode 8 as a regular file. On a volume whose superblock has the RECOVER incompat flag set, pending committed transactions are replayed into the filesystem before normal use, then the journal is reset and the flag cleared — which is what makes a power loss survivable rather than corrupting.

Two things to know. The journal's on-disk structures are big-endian, unlike the rest of ext — a genuine trap when reading the code. And only the classic non-checksummed format is handled (ext3, and ext4 with ^metadata_csum); a checksummed journal (CSUM_V2/V3) raises Unsupported_Feature rather than guessing.

Formatting on the device

Ext4.Mkfs lays down a fresh minimal ext4 directly on a Block_Dev: one block group, a root directory and lost+found, no journal, no metadata_csum. The result mounts read-write with this filesystem and passes the host's e2fsck — which is the claim worth making, because it means the format is genuinely correct rather than merely self-consistent.

It writes only metadata and the two directory blocks, leaving data blocks untouched (the filesystem initialises each as it is allocated). So formatting a 32 MB part is fast, but it also means Mkfs is not an erase — old file contents remain on the medium until overwritten.

Targets the embedded/full runtimes: it needs exceptions, finalization, secondary stack and a heap.