M9: user-space VFS server + client file API (open/read/write/stat + stdio)
The payoff milestone: files are served by a user-space process, reached over
IPC — the kernel never sees a path or an fd.
- lib/vfs_proto.zig: the VFS wire protocol (Op, Request/Reply fixed header +
inline payload, Stat), shared by client and server; one message <= MSG_MAX.
- lib/ipc.zig: replyWait() — the server-side dual-return stub (length in rax,
badge in rdx via a "+{rdx}" read-write operand), deferred from M7.
- sbin/vfs.zig: the real VFS server — an in-heap ramfs (open creates a node)
with an IPC_ReplyWait dispatch loop serving open/read/write/stat/close.
Registers its endpoint under the well-known vfs id at startup.
- lib/unistd.zig: POSIX-style client API in rt — a per-process fd table +
open/close/read/write/lseek/stat, each an IPC_Call to the VFS. The kernel
knows nothing of fds; the table lives here.
- lib/stdio.zig: C stdio over unistd — FILE + fopen/fclose/fread/fwrite/
fseek/ftell/rewind/feof/ferror/fputs/fputc/fgetc (unbuffered for now).
- sbin/vfstest.zig: a client that opens/writes/seeks/reads a file and only
heartbeats "vfstest: ok" if the round trip matched. Packed in the initrd.
- New `vfs` test drives it end to end. initrd test relaxed to generic
liveness. Suite 31/31.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
//! /sbin/vfstest — a client that proves the VFS round trip end to end: open a
|
||||
//! file through the `rt` file API, write to it, seek back, read it, and compare.
|
||||
//! On success it heartbeats "vfstest: ok" so the kernel test can observe it;
|
||||
//! on failure it reports what went wrong. Shipped in the initrd alongside vfs.
|
||||
|
||||
const std = @import("std");
|
||||
const rt = @import("rt");
|
||||
|
||||
pub fn main() void {
|
||||
const u = rt.unistd;
|
||||
const payload = "hello-vfs";
|
||||
|
||||
// The VFS server may not have registered yet — retry open until it's up.
|
||||
var fd: i32 = -1;
|
||||
var tries: u32 = 0;
|
||||
while (fd < 0 and tries < 200) : (tries += 1) {
|
||||
fd = u.open("greeting", u.O_CREAT);
|
||||
if (fd < 0) rt.sys.sleep(20);
|
||||
}
|
||||
if (fd < 0) {
|
||||
_ = rt.sys.write("vfstest: open failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (u.write(fd, payload) != @as(isize, payload.len)) {
|
||||
_ = rt.sys.write("vfstest: write failed\n");
|
||||
return;
|
||||
}
|
||||
_ = u.lseek(fd, 0, u.SEEK_SET);
|
||||
|
||||
var buf: [32]u8 = undefined;
|
||||
const n = u.read(fd, &buf);
|
||||
u.close(fd);
|
||||
|
||||
if (n == @as(isize, payload.len) and std.mem.eql(u8, buf[0..@intCast(n)], payload)) {
|
||||
while (true) {
|
||||
_ = rt.sys.write("vfstest: ok\n");
|
||||
rt.sys.sleep(1000);
|
||||
}
|
||||
}
|
||||
_ = rt.sys.write("vfstest: mismatch\n");
|
||||
}
|
||||
|
||||
pub const panic = rt.panic;
|
||||
comptime {
|
||||
_ = &rt.start._start;
|
||||
}
|
||||
Reference in New Issue
Block a user