4 Commits
Author SHA1 Message Date
Daniel Samson bf9f8560c6 fat/harness: filesystems coexist without the shared vfs name; two-volume proof (S3)
A second usb-storage device (a generated data volume, serial da7a0001,
an empty FAT with no /system) plugged in beside the boot volume: the
volume manager adopts both devices and spawns a confined fat per volume,
each mounted at its own content id-path.

The test surfaced a real coexistence bug. Every filesystem bound the
single "vfs" contract name under /protocol; the second volume's fat lost
the race, service.run refused-and-exited on the held name, and that
volume never mounted. Clients don't reach filesystems by that name —
fs_resolve routes a path to its backing endpoint through the kernel
mount table by prefix — and nothing consumes "vfs", so the fix is to
bind no shared name: the harness's service_name now defaults to null.
This is the "this fades" the harness comment anticipated for the
volume-manager era; a filesystem's endpoint still serves as its mount
backend without a name.

fat logs "is a data volume" for the non-system branch so the test can
positively assert content-based detection. make-fat-image gains
--serial/--label (default unchanged) so a second image gets a distinct
id-path; the data image is generated per run, never committed. The case
fails against the pre-fix harness (the data volume's fat exits on the
refused bind) — toggle-demonstrated.

Full suite 129/129 (128 + two-volumes); the single-volume path is
unaffected by dropping the vestigial name bind.
2026-08-10 02:10:06 +01:00
Daniel Samson b9058fe020 file-system: the mount-failure log has no scratch buffer (orphaned bounds fix)
The mount-failure diagnostic wrote through a fixed [96]u8 bufPrint buffer,
which the bounds gate flags as an undeclared ceiling. Three ring appends
instead — no buffer, no fixed length to justify. This fix was made during
the V2a bounds work but never git-added, so the committed harness still
carried the flagged buffer; committing it now cleans the tip.
2026-08-09 19:40:39 +01:00
Daniel Samson 7ea54a84e5 file-system: mount-failure diagnostics go to the kernel ring, not std.log
V1 boundary review (4 reviewers converged): the extraction routed mount-
FAILURE logs through std.log where old fat used logging.write. That matters
precisely when the failed mount IS /system/logs — a std.log record would
then have nowhere to land. Restore the direct kernel-ring write for the
failure branch (generic prefix, since the harness is filesystem-agnostic
now); success stays std.log.info as before. Unexercised error path; fat-mount
still green. Everything substantive in the extraction verified neutral.
2026-08-09 17:06:13 +01:00
Daniel Samson d63a008148 file-system: extract the serving harness from fat — V1
fat was one binary doing four jobs; the three that are not FAT-specific move
to library/kernel/file-system-harness, a Server(comptime Engine) generic over
the engine type: the badge-scoped open-node table, the nine vfs handlers, the
not-mounted politeness, the exit sweep, mount registration, and durable-on-
close. A filesystem is now an engine plus a main that hands the harness a
mounted volume; a second engine reuses the harness wholesale.

Placement note: the plan said library/file-system, but the harness is a
specialization of `service` (its sibling) and needs nothing from the device
domain, so it lives beside service in library/kernel and stays block-free —
durability rides a caller closure (Volume.flush), no backwards kernel->device
dependency, no new-domain scaffolding. The engine type is inferred from
resolve()'s return, so engine.zig is untouched (its Node stays module-scope).

fat keeps only its FAT-specific bring-up (acquireVolume, DMA, engine.mount,
the attach/detach round trip) and the three mount prefixes as data. Behavior-
neutral: 13/13 across the fat/vfs/logger/IOMMU surface, nothing observable
changed. This lands first so every later phase touches the harness once.
2026-08-09 16:55:48 +01:00