The filesystem
EFS is the native filesystem. It is, in the author’s own description, “ext2 with extents”: block groups with per-group bitmaps and inode tables, and extents in place of indirect block pointer trees.
The full on-disk specification lives in the repository. This page is the shape of it.
Properties
Section titled “Properties”- Block groups, each with a block bitmap, an inode bitmap and an inode table.
- Extent-based block mapping. No indirect blocks.
- Inline data: a file up to 176 bytes lives entirely inside its inode.
- 256-byte inodes with 64-bit nanosecond timestamps.
- CRC32 checksums on every major on-disk structure.
- Feature flags, split into compatible, incompatible and read-only-compatible, so a future format change fails a mount instead of corrupting one.
- A metadata write-ahead journal, mandatory via
INCOMPAT_JOURNAL.
What it deliberately is not: copy-on-write, so there are no snapshots; and not a data
journal, so file contents are not crash-safe. The semantics are data=writeback.
The journal
Section titled “The journal”Metadata changes are written to the journal and committed before the corresponding blocks are allowed to reach their final location. Mounting checks the journal and replays it if the last unmount was unclean. On a clean boot the log says so:
[1.624278] <cpu-0:fs:k:14> efs journal: clean, no replay neededA dedicated journal_committer kernel thread commits transactions, and
block_writeback flushes dirty pages only once the journal says it is safe. That gating
is the reason the two are separate threads rather than one.
The caches
Section titled “The caches”Three layers sit between a read and the disk:
| Layer | What it holds |
|---|---|
| Page cache | file pages, per inode, with read-ahead and asynchronous fill |
| Block page cache | sharded raw block cache under the filesystem, and the journal’s own view |
| AHCI | up to 32 NCQ commands in flight, submitted and completed by separate halves of the driver |
Two rules govern them, and both exist because breaking them caused real hangs: page-cache
locks and block-cache shards are never held across disk I/O, and inode.lock is released
before any I/O the VFS performs on behalf of a write.
Other filesystems
Section titled “Other filesystems”| Filesystem | Where |
|---|---|
| EFS | the root |
| FAT32 | read and write, used for EFI system partitions and interoperability |
| devfs | /dev: fb, tty0, dsp, kbd, mouse, random, klog |
| procfs | /proc: counters and process state |
| memfs | /tmp, and the fallback root when no root= is given |
Host tools
Section titled “Host tools”tools/efs-mkfs formats a partition and can populate it from a directory in one pass;
make sata-disk.img and the live-root image both use it. The same formatter is built as
a userspace program, so edos-install creates an EFS root from inside EDOS with one
implementation rather than two that can drift.
tools/efs-fsck checks an image and, with --repair, fixes what it safely can,
including reclaiming inodes the kernel dropped under pressure rather than stalling a
dying thread behind disk I/O.
Reaching a disk from userspace
Section titled “Reaching a disk from userspace”devfs exposes one node per block device, /dev/sda and /dev/sdb, with byte-granular
read and write, plus ioctls to flush, rescan the partition table, read the sector count,
and ask whether the device backs a mount. Reads and writes go through the block page
cache rather than around it, keyed by the same (device, page) the filesystem driver
will use moments later; a node that bypassed the cache would leave stale pages behind and
produce an install that looks fine and does not boot.
Writing to a device that backs a mounted filesystem is refused.