From 0a21ea831d6791b406eef70b3e95cfd319d8ed36 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Thu, 27 Aug 2026 15:28:21 -0300 Subject: fs_service: the transport is a ctx and three functions, not a *fuse.Fs Step 2 of the 9P chain (docs/9p.typ 12.2, docs/registry.typ 9P-2). `drain` and `step` never asked a `*fuse.Fs` for anything but `retry()`, `next()` and `reply()`, so the concrete pointer was a coupling that bought nothing and forbade a second answer. `Transport` names the three; `Fs.transport()` is the first implementor and the thunks are the entire cost. No behaviour change. The order contract -- retry() to null, then next() to null -- moves into `drain`'s doc comment, where it belongs: it is the caller's rule and every implementor inherits it, rather than a fact about FUSE. `start` and `wake` keep their `*fuse.Fs`: they are about a MOUNT, which is a FUSE thing, and a 9P listener will bring its own. Measured unchanged against zig build fs-bench -Doptimize=ReleaseFast: getattr 19 ns, lookup 40, read body 4K/1M 25/25, read ctl 385, read index 633, readdir 38, read event (empty) 22, all at zero allocations. --- src/detached/server.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/detached/server.zig') diff --git a/src/detached/server.zig b/src/detached/server.zig index 4437cc22..9a8dc24f 100644 --- a/src/detached/server.zig +++ b/src/detached/server.zig @@ -952,7 +952,7 @@ pub const Session = struct { // in the surface this frame composes, not the next one. The flag is // read by `waitInput`, which must not sleep while the kernel still has // requests we have not acknowledged. - if (s.fs) |f| s.fs_pending = fs_service.drain(f, s.core).pending; + if (s.fs) |f| s.fs_pending = fs_service.drain(f.transport(), s.core).pending; for (&s.ptys, 0..) |*pt, pane| { if (pt.fd < 0) continue; var lbuf: [1024]u8 = undefined; -- cgit v1.3