kernel: VFS root — mount table, /system from the initrd, fs syscalls
system/kernel/vfs.zig is the resolve+redirect router: fs_resolve (#46) walks the kernel mount table; a path under the kernel-backed /system mount (the initrd, seeded by setInitialRamdisk with a derived directory table) yields a permanent stateless node token served by fs_node (#47) — read/status/readdir with copy-out, initrd reads lock-free — while a path under a userspace mount yields the backend's endpoint (installed in the caller's table, DEDUPLICATED so 16 slots can't be exhausted by repeated resolves) plus the rewritten mount-relative path; the caller then speaks the unchanged vfs-protocol rendezvous directly. The kernel never blocks on a userspace filesystem, holds no open-file state, and refuses create-intent on the immutable /system. fs_mount (#48) is the syscall form of the old router's op-6 cap-pass (possession of the backend handle is the capability; an optional rewrite prefix maps the mount into the backend's namespace — how /var will reach the flash volume); fs_unmount (#49) removes one. A dead backend's mount clears lazily on resolve. Dormant this milestone: the userspace vfs still serves runtime.fs unchanged; the kvfs QEMU case covers the kernel side (resolution, ELF magic read-through, /system listing, read-only + unknown refusals) until the M-G cutover exercises the syscalls end-to-end.
This commit is contained in:
@@ -72,6 +72,10 @@ pub const SystemCall = enum(u64) {
|
||||
thread_join = 43, // thread_join(tid) -> 0: block until the thread with id `tid` has exited (runtime.Thread.join; no per-thread IPC endpoint) (docs/threading.md)
|
||||
set_thread_pointer = 44, // set_thread_pointer(addr) -> 0: set the caller's thread pointer (user-space TLS base; x86_64 IA32_FS_BASE, aarch64 TPIDR_EL0); restored per task across context switches (docs/threading-plan.md M10)
|
||||
klog_status = 45, // klog_status(ptr) -> 0: copy a KlogStatus (ring cursors + the boot wall-clock anchor) out to a user buffer
|
||||
fs_resolve = 46, // fs_resolve(path_ptr, path_len, flags, out_ptr, out_cap) -> route tag (rax: fs_route_*) + node token or backend handle (rdx); a backend resolve writes the rewritten mount-relative path into out (length in r8 via third result)
|
||||
fs_node = 47, // fs_node(op, node_token, offset, buf_ptr, buf_len) -> bytes/0/-errno: read/status/readdir on a kernel-served node (op values mirror the vfs-protocol Operation numbers)
|
||||
fs_mount = 48, // fs_mount(prefix_ptr, prefix_len, backend_handle, rewrite_ptr, rewrite_len) -> 0/-errno: mount a userspace filesystem's endpoint at an absolute prefix (possession of the handle is the capability)
|
||||
fs_unmount = 49, // fs_unmount(prefix_ptr, prefix_len) -> 0/-errno: remove a backend mount
|
||||
_,
|
||||
};
|
||||
|
||||
@@ -225,6 +229,45 @@ pub const klog_record_alignment: usize = 8;
|
||||
/// Per-record payload cap (one line; longer emitter lines are truncated).
|
||||
pub const klog_maximum_message: usize = 256;
|
||||
|
||||
// --- the kernel VFS root (resolve + redirect) --------------------------------
|
||||
// fs_resolve routes a path through the kernel mount table. Kernel-backed mounts
|
||||
// (the initrd at /system) resolve to a permanent node TOKEN served by fs_node;
|
||||
// userspace mounts resolve to the backend's endpoint handle (installed in the
|
||||
// caller's table, deduplicated) plus the rewritten mount-relative path — the
|
||||
// caller then speaks the vfs-protocol to the backend directly. The kernel never
|
||||
// blocks on a userspace filesystem.
|
||||
|
||||
/// fs_resolve result tags (rax).
|
||||
pub const fs_route_kernel: u64 = 0; // rdx = node token; serve via fs_node
|
||||
pub const fs_route_backend: u64 = 1; // rdx = endpoint handle; speak vfs-protocol
|
||||
|
||||
/// fs_node operations — the same numbers as the vfs-protocol Operation enum, so
|
||||
/// client code shares one vocabulary.
|
||||
pub const fs_node_read: u64 = 2;
|
||||
pub const fs_node_status: u64 = 4;
|
||||
pub const fs_node_readdir: u64 = 5;
|
||||
|
||||
/// fs_resolve flags (same values as the vfs-protocol open flags).
|
||||
pub const fs_flag_create: u64 = 1;
|
||||
|
||||
/// FileStatus-shaped node metadata (matches the vfs-protocol payload layout).
|
||||
pub const file_kind_regular: u32 = 0;
|
||||
pub const file_kind_directory: u32 = 1;
|
||||
pub const FileAttributes = extern struct {
|
||||
size: u64,
|
||||
kind: u32,
|
||||
_pad: u32 = 0,
|
||||
mtime: u64 = 0,
|
||||
};
|
||||
|
||||
/// One fs_node readdir result: the header, followed by `name_len` name bytes in
|
||||
/// the caller's buffer (matches the vfs-protocol DirectoryEntry layout).
|
||||
pub const DirectoryEntryHeader = extern struct {
|
||||
kind: u32,
|
||||
name_len: u32,
|
||||
size: u64,
|
||||
};
|
||||
|
||||
/// The klog_status copy-out: the ring's live cursors plus the wall-clock time
|
||||
/// of boot — the anchor a log persister names its per-boot directory with and
|
||||
/// combines with record timestamps for wall-clock line stamps.
|
||||
|
||||
Reference in New Issue
Block a user