Sixty-five headers sat side by side in include/, so `#include "irq.h"` said nothing about where irq.h was or what it belonged to, and errno.h, stat.h and fcntl.h at the top shadowed the system's for any host tool built with -I./include. They are in folders now -- arch/ core/ fs/ dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and every include names the folder, as Linux's do: "core/proc.h". Done mechanically and checked the hard way: the kernel built from this tree disassembles identically to the one built from the tree before it. The full image boots, and userland is the same set of programs. Paths in docs and comments follow; docs/guides/layout.md has a table of what is where, and tools/fix-includes.py rewrites old-style includes from the folders in the tree, for code written before this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
2.3 KiB
| name | description | metadata | ||
|---|---|---|---|---|
| schunix-dirsiz-14 | DIRSIZ was 14 and truncated silently; raised to 30 on 2026-08-09 by holding the HTree bucket at 256 bytes. |
|
Found 2026-08-09 while staging fonts. DIRSIZ in include/fs/fs.h is 14, an
xv6 inheritance, and the v1 filesystem truncates to it silently.
JetBrainsMono-Regular.ttf was stored as JetBrainsMono-. Two consequences,
the second much worse than the first:
- The file cannot be opened by its real name, and
statfails on it —ls -lshowed?for every field, which is what tipped this off. JetBrainsMono-Regular.ttfandJetBrainsMono-Bold.ttfboth truncate toJetBrainsMono-. Any set of files sharing a 14-character prefix collides. That is silent data loss, not a display limitation.
Fixed the same day: DIRSIZ is 30
The trick that made it safe: hold the HTree bucket at 256 bytes.
The directory hash tree is laid out in bytes, not entries. A bucket was 16
slots x 16 bytes = 256, and HASHRANGE, OVERFLOW_DIR_START (113 * BSIZE),
OVERFLOW_DIR_END and MAXFSIZE are all derived from that. Raising DIRSIZ
naively to 62 would have made buckets 1024 bytes and pushed the primary area
from 117 KB to 470 KB, straight through the overflow region -- silent corruption
of every directory.
DIRSIZ 30 makes struct dirent exactly 32 bytes, so a 256-byte bucket holds
8 slots instead of 16 and every byte offset in the layout is unchanged.
DIRENT_BUCKET_BYTES in include/fs/fs.h is now the constant the maths is written
against; kernel/fs/fs.c and tools/mkfs.c both use it instead of
16 * sizeof(struct dirent). Cost: more overflow use in heavily collided
directories.
Verified in the running system: /usr/share/fonts lists
JetBrainsMono-Regular.ttf in full, and /tmp/JetBrainsMono-Regular.txt and
/tmp/JetBrainsMono-Bold.txt coexist with distinct contents -- the exact case
that used to collapse into one entry. All four bootcheck modes pass.
Still not POSIX's 255. Getting there means reshaping the directory format, which wants the on-disk version policy SchFS is getting first. 30 covers real filenames; it is not a general solution.
sysroot/bin's 244 toybox links were checked for collisions at the old limit:
there were none, so nothing was silently broken before this.