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.
This commit is contained in:
Daniel Samson
2026-08-10 02:10:06 +01:00
parent da7dcce64e
commit bf9f8560c6
4 changed files with 79 additions and 11 deletions
+8 -4
View File
@@ -61,10 +61,14 @@ pub fn Server(comptime Engine: type) type {
/// caller does the filesystem-specific bring-up (find the block
/// device, set up DMA, mount the engine) and returns a `Volume`.
bringUp: *const fn (endpoint: ipc.Handle) ?Volume,
/// The vfs contract name to bind. A filesystem serving one volume
/// binds "vfs" today; the volume-manager era hands each per-volume
/// process its own establishment and this fades.
service_name: ?[]const u8 = "vfs",
/// A contract name to bind under /protocol, or null to bind none. In
/// the volume-manager era every filesystem is a per-volume process and
/// clients reach it through the kernel mount table — fs_resolve routes
/// a path to its backing endpoint by prefix — so no filesystem binds a
/// shared name. Two volumes would collide on one: the second's bind is
/// refused and service.run would exit, so its volume never mounts. The
/// endpoint still serves as the mount backend without a name.
service_name: ?[]const u8 = null,
};
// --- the harness's own state, one set per instantiation ---------------