diff --git a/CLAUDE.md b/CLAUDE.md index 2e89c781e4d..5e480bcea0b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -39,11 +39,11 @@ There are no spec documents. A rule a reader can check lives in an agent's promp **Userspace servers** — `system.toml` names them. Each claims a device or capability from the kernel and serves its function; crash one and the kernel is fine. -**The log is a userland file.** `/system/bin/logd` reads records on a cursor and owns `/log`; the kernel keeps the record ring, the console and the panel, and writes no file. `SYS_FSYNC` reaches the device's cache flush because logd's durability claim rests on it. +**The log is a userland file.** `/system/bin/logkeeper` reads records on a cursor and owns `/log`; the kernel keeps the record ring, the console and the panel, and writes no file. `SYS_FSYNC` reaches the device's cache flush because logkeeper's durability claim rests on it. **Syscall ABI** — `toyos-abi/`: struct layouts, syscall numbers, typed wrappers; completely unstable. The cleanest, most sustainable ABI beats convenience; a removed number is free. `toyos/` builds on it with typed handles, IPC framing, ports, namespaces and `surface` — userland uses `toyos`, the kernel uses `toyos-abi` only. -**Capabilities** — a process holds exactly what its parent moved into it, and among kernel objects there is nothing it can name to get more. No registry, no connect-by-name, no pid-as-authority: `/system/bin/init` builds every program's namespace and device claims from `system.toml` before spawning it, and a handle a process does not hold is a bug in that process — the kernel ends it rather than answering a word it can ignore. **Isolation is non-negotiable, and the filesystem is inside it**: a process names only the paths in the view its parent built for it, the unit of isolation is the program, and a user is the part of the tree a session was handed. Not yet true of files: the kernel still resolves every path against one machine-wide tree until the storage track's per-program views land. +**Capabilities** — a process holds exactly what its parent moved into it, and among kernel objects there is nothing it can name to get more. No registry, no connect-by-name, no pid-as-authority: `/system/bin/supervisor` builds every program's namespace and device claims from `system.toml` before spawning it, and a handle a process does not hold is a bug in that process — the kernel ends it rather than answering a word it can ignore. **Isolation is non-negotiable, and the filesystem is inside it**: a process names only the paths in the view its parent built for it, the unit of isolation is the program, and a user is the part of the tree a session was handed. Not yet true of files: the kernel still resolves every path against one machine-wide tree until the storage track's per-program views land. **CPU state** — a CPU's control registers come from one declaration, applied by the BSP and by every AP and asserted on each; no read-modify-write decides what either holds. diff --git a/Cargo.toml b/Cargo.toml index 430cc331c72..36ab963d8b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -136,16 +136,16 @@ toyos-fat32 = { path = "toyos-fat32" } toyos-fat32-check = { path = "toyos-fat32/check" } toyos-gpt = { path = "toyos-gpt" } toyos-keymap = { path = "toyos-keymap" } -# The form a program's line takes in a boot's log and the port `logd` serves it -# on, so the judges reading the log and `logd` writing it read one declaration. +# The form a program's line takes in a boot's log and the port `logkeeper` serves it +# on, so the judges reading the log and `logkeeper` writing it read one declaration. toyos-logstream = { path = "toyos-logstream" } toyos-manifest = { path = "toyos-manifest" } # The shutdown's stop record: the kernel renders it and this crate reads it back # off a stick, so one declaration is what both sides spell it with. toyos-quiesce = { path = "toyos-quiesce" } # The swap port's name and the one program the image may give it to, so the -# gate on every manifest and the host that asks for a swap read what init and -# sshd read. +# gate on every manifest and the host that asks for a swap read what the supervisor and +# sshserver read. toyos-swap = { path = "toyos-swap" } # The watchdog's parameter name, so the gate over `kernel/src/params.rs` reads # the same constant the kernel and the bootloader do. @@ -159,8 +159,8 @@ toyos-blackbox = { path = "toyos-blackbox" } toyos-update = { path = "toyos-update", features = ["sign"] } # A throwaway key's seed, from the operating system. Already resolved here. getrandom = "0.3" -# `classify`, so the host reading a log volume and `logd` writing it cannot -# disagree about which files on it are `logd`'s. +# `classify`, so the host reading a log volume and `logkeeper` writing it cannot +# disagree about which files on it are `logkeeper`'s. toyos-wallclock = { path = "toyos-wallclock" } image = { version = "0.25", default-features = false, features = ["jpeg"] } # The digest behind `NOTICE`'s record of every committed binary file @@ -181,7 +181,7 @@ ureq = { version = "3", default-features = false, features = ["rustls"] } # checks every user pointer against and not against a second copy of it. toyos-userbound = { path = "toyos-userbound" } # The I219 driver's own words and its PHY probe's exit-code table, so the -# harness judging netd's `exit:` record off the T14 and netd writing it read one +# harness judging netstack's `exit:` record off the T14 and netstack writing it read one # declaration. Pure and `no_std`, so it compiles for the host as it does for # the guest. toyos-i219 = { path = "toyos-i219" } diff --git a/bcachefs/tests/integration.rs b/bcachefs/tests/integration.rs index 4b95bf8386a..838c7071256 100644 --- a/bcachefs/tests/integration.rs +++ b/bcachefs/tests/integration.rs @@ -1266,7 +1266,7 @@ fn a_filesystems_name_round_trips_through_its_superblock() { } let mut fs = Formatted::format(VecBlockIO::new(128)).expect("format"); - fs.create("bin/init", b"init-binary", 0).expect("create"); + fs.create("bin/supervisor", b"supervisor-binary", 0).expect("create"); fs.set_uuid(named); let raw = fs.into_io().expect("finish").into_vec(); let mounted = diff --git a/bootloader/src/attempt.rs b/bootloader/src/attempt.rs index 5104349b588..069705f9ce0 100644 --- a/bootloader/src/attempt.rs +++ b/bootloader/src/attempt.rs @@ -15,7 +15,7 @@ use crate::loaderlog; /// The file, at the root of the log partition beside `loader.log`. /// -/// Not one of `logd`'s names and not the loader's log: a reader of the volume +/// Not one of `logkeeper`'s names and not the loader's log: a reader of the volume /// that walks it for either finds this and passes over it /// (`toyos_build::bootlog::split_listing`). const NAME: &CStr16 = cstr16!("attempts"); diff --git a/bootloader/src/loaderlog.rs b/bootloader/src/loaderlog.rs index 27b40295364..615566ca9b0 100644 --- a/bootloader/src/loaderlog.rs +++ b/bootloader/src/loaderlog.rs @@ -5,7 +5,7 @@ //! //! The file is `loader.log` at the root of the partition //! `KernelArgs::log_partition_guid` names, truncated at each boot. One file -//! under a fixed name and never one of `logd`'s timestamped ones, so a reader +//! under a fixed name and never one of `logkeeper`'s timestamped ones, so a reader //! looking for the kernel's log on this volume never picks this up. //! //! A partition this cannot open or write is refused by name on the console and diff --git a/console/system.toml b/console/system.toml index a0b96aa1f17..f6f992dee83 100644 --- a/console/system.toml +++ b/console/system.toml @@ -5,7 +5,7 @@ # boot checkpoint stays on the glass — which is the only thing that works on a # machine that wedges before userland, and is the answer to exactly one # question. This image answers the rest by being asked them: `/system/bin/console` -# claims the screen, shows this boot's log as `logd` serves it — the kernel's +# claims the screen, shows this boot's log as `logkeeper` serves it — the kernel's # records and every program's output — so nothing is lost with the checkpoint, # and puts a prompt underneath. # @@ -16,17 +16,17 @@ assets = ["assets"] [boot] -start = ["logd", "blockd", "fsd", "console"] +start = ["logkeeper", "diskserver", "fileserver", "console"] # `/system/bin/console` owns the screen and provides the surface its shell and the # shell's children inherit. No compositor here, so nothing receives one. # **Every image that carries a `TOYOS-LOG` partition runs this**, and every # image does. The kernel keeps the record ring and the console and writes no -# file at all, so a boot config without `logd` is a boot whose `/log` is empty — -# `every_boot_config_runs_logd` is what refuses one. It claims no device; it +# file at all, so a boot config without `logkeeper` is a boot whose `/log` is empty — +# `every_boot_config_runs_logkeeper` is what refuses one. It claims no device; it # reads the kernel's records with `logread`, which is `Rights::LOG | # Rights::WAIT` on a `SysCap` duplicate, and serves `log` to the console. -[programs.logd] +[programs.logkeeper] service = true syscap = ["logread"] serves = ["log"] @@ -41,7 +41,7 @@ receives = ["surface", "launcher"] # `power` because `bin/shutdown` below is this binary, and on the machine this # image exists for — no serial port, a prompt on the panel — there is no other -# way to turn it off: it asks init, which has `logd` make the log whole first. +# way to turn it off: it asks the supervisor, which has `logkeeper` make the log whole first. # `roster` because `bin/ps` is the same binary and this image exists to be # asked what the machine is doing. [programs.toybox] @@ -68,7 +68,7 @@ syscap = ["roster"] # The block service: the NVMe controller this machine's DATA is on, driven # from userland through its claim. Started again when it ends; the claim goes # back with the process and is minted again for the next. -[programs.blockd] +[programs.diskserver] service = true restart = true serves = ["block"] @@ -77,7 +77,7 @@ devices = ["pci:1b36:0010"] # The file servers: DATA, the log and the running slot's volume, one process # each, serving every program the directories of its role. Started again when # one ends, on the same ports. -[programs.fsd] +[programs.fileserver] restart = true roles = ["data", "log", "boot"] receives = ["block"] diff --git a/diag/system.toml b/diag/system.toml index 3888d960e60..b19369c177d 100644 --- a/diag/system.toml +++ b/diag/system.toml @@ -8,34 +8,20 @@ # kernel logged — including the one `i8042:` line that says why the integrated # keyboard is dead — was on screen for about a tenth of a second and then gone. # -# `/system/bin/init` is in every image and holds the one `SysCap`, so the guarantee is -# no longer "nothing here *can* claim the framebuffer" but "this config declares -# no `devices`" — which `no_diag_program_claims_the_screen` checks before the -# image is written, and which nothing checked before. The reachable set is the -# same; a bug in init could reach a device where previously no code in the image -# could, and that is the trade. -# -# **Two programs now, and the guarantee is restated rather than assumed.** It -# used to be "nothing here can claim the framebuffer, because the compositor is -# not built into this image at all". `logd` is in this image because the kernel -# writes no file, and an unchanged config here would flash a T14 that logs to a -# panel and nowhere else. The argument survives verbatim: `logd` declares no -# `devices` at all — its whole row is `syscap = ["logread"]` — so the reachable -# set is unchanged and `no_diag_program_claims_the_screen` still checks it -# before the image is written. -# -# The other program it starts prints the cwd and exits. +# `/system/bin/supervisor` is in every image and holds the one `SysCap`, so the +# guarantee is that this config declares no `devices`, which +# `no_diag_program_claims_the_screen` checks. [boot] -start = ["logd", "fsd", "toybox"] +start = ["logkeeper", "fileserver", "toybox"] # **Every image that carries a `TOYOS-LOG` partition runs this**, and every # image does. The kernel keeps the record ring and the console and writes no -# file at all, so a boot config without `logd` is a boot whose `/log` is empty — -# `every_boot_config_runs_logd` is what refuses one. It claims no device and +# file at all, so a boot config without `logkeeper` is a boot whose `/log` is empty — +# `every_boot_config_runs_logkeeper` is what refuses one. It claims no device and # serves no port: its row's authority is `logread`, which is -# `Rights::LOG | Rights::WAIT` on a `SysCap` duplicate, and init hands it every +# `Rights::LOG | Rights::WAIT` on a `SysCap` duplicate, and the supervisor hands it every # program's output beside that. -[programs.logd] +[programs.logkeeper] service = true syscap = ["logread"] @@ -45,6 +31,6 @@ args = ["pwd"] # `/log`'s file server, and only it: the log partition is the kernel's # partition claim on the boot stick, so this row declares no `devices`, and # DATA's block service would be one. -[programs.fsd] +[programs.fileserver] restart = true roles = ["log"] diff --git a/issues/audio/a-client-cannot-tell-soundd-it-paused.md b/issues/audio/a-client-cannot-tell-soundserver-it-paused.md similarity index 100% rename from issues/audio/a-client-cannot-tell-soundd-it-paused.md rename to issues/audio/a-client-cannot-tell-soundserver-it-paused.md diff --git a/issues/audio/cpal-backend-hardcodes-the-format.md b/issues/audio/cpal-backend-hardcodes-the-format.md index 7b341a81daf..29342949b46 100644 --- a/issues/audio/cpal-backend-hardcodes-the-format.md +++ b/issues/audio/cpal-backend-hardcodes-the-format.md @@ -35,7 +35,7 @@ and the cpal backend's `pause()` is a purely local futex store soundd is never told about. No change confined to soundd can separate the two, and landing the soundd and SDK halves alone would kill every paused cpal client. The **protocol**, not the implementation, is what needs to change; -`issues/audio/a-client-cannot-tell-soundd-it-paused.md` is that change. +`issues/audio/a-client-cannot-tell-soundserver-it-paused.md` is that change. The assignment was reclaimed 2026-08-23: nobody holds it, and the block above is what it is waiting on. diff --git a/issues/boot-media/an-image-on-a-disk-blockd-drives-cannot-write-its-slots.md b/issues/boot-media/an-image-on-a-disk-diskserver-drives-cannot-write-its-slots.md similarity index 100% rename from issues/boot-media/an-image-on-a-disk-blockd-drives-cannot-write-its-slots.md rename to issues/boot-media/an-image-on-a-disk-diskserver-drives-cannot-write-its-slots.md diff --git a/issues/boot-media/logd-ends-the-boots-log-on-one-refused-create-and-nothing-durable-says-so.md b/issues/boot-media/logkeeper-ends-the-boots-log-on-one-refused-create-and-nothing-durable-says-so.md similarity index 100% rename from issues/boot-media/logd-ends-the-boots-log-on-one-refused-create-and-nothing-durable-says-so.md rename to issues/boot-media/logkeeper-ends-the-boots-log-on-one-refused-create-and-nothing-durable-says-so.md diff --git a/issues/boot-media/the-loader-does-only-what-must-precede-the-handover.md b/issues/boot-media/the-loader-does-only-what-must-precede-the-handover.md index 9718d54d137..9a9ef8ca1d4 100644 --- a/issues/boot-media/the-loader-does-only-what-must-precede-the-handover.md +++ b/issues/boot-media/the-loader-does-only-what-must-precede-the-handover.md @@ -338,7 +338,7 @@ Each stage lands on its own, in this order. `issues/hardware/the-t14-redial-re-asks-mdns-after-every-refusal.md`, `issues/diagnostics/a-first-dial-turned-away-before-a-line-is-waited-on-to-its-callers-bound.md` and - `issues/diagnostics/a-netd-that-dies-while-serving-leaves-the-hosts-stream-silent.md`. + `issues/diagnostics/a-netstack-that-dies-while-serving-leaves-the-hosts-stream-silent.md`. - #539's issues `a-loader-change-reaches-a-machine-only-by-writing-its-stick`, `the-bench-reads-no-quiescent-log-volume`, `the-bench-runs-with-no-bound-on-its-own-boot`, diff --git a/issues/build/soundds-mix-pass-has-no-host-test.md b/issues/build/soundservers-mix-pass-has-no-host-test.md similarity index 100% rename from issues/build/soundds-mix-pass-has-no-host-test.md rename to issues/build/soundservers-mix-pass-has-no-host-test.md diff --git a/issues/build/the-std-forks-toyos-files-carry-lines-rustfmt-would-rewrap.md b/issues/build/the-std-forks-toyos-files-carry-lines-rustfmt-would-rewrap.md new file mode 100644 index 00000000000..b0469c600af --- /dev/null +++ b/issues/build/the-std-forks-toyos-files-carry-lines-rustfmt-would-rewrap.md @@ -0,0 +1,29 @@ +--- +status: open +kind: defect +opened: 2026-10-03 +--- + +# The std fork's ToyOS files carry lines rustfmt would rewrap + +Under `rust/rustfmt.toml`, the rustfmt `rust/src/stage0` pins (`1.9.0-nightly +77cf889bc1`, which applies the config's `group_imports` and +`imports_granularity`) rewrites seven places in four of the `rust` fork's +ToyOS files under `library/std` at `a0d44493347`, each file checked on its own +text (`rustfmt --check --config-path rustfmt.toml --edition 2024`). Stable +1.9.0, which skips those two options, rewrites the same seven: + +| file | places | +|---|---| +| `src/os/toyos/fs.rs` | 1 | +| `src/sys/fs/toyos.rs` | 2 | +| `src/sys/pal/toyos/mod.rs` | 2 | +| `src/sys/process/toyos.rs` | 2: the three `setup_slot` calls and the `Outcome::Gone` arm | + +A fork change is written as upstream would take it, and upstream formats +`library/std` with that configuration. + +**Owner**: the `rust` fork. + +**Exit**: the rustfmt `rust/src/stage0` pins, under `rust/rustfmt.toml` with +its two import options, changes no ToyOS file under `library/std`. diff --git a/issues/build/wait-until-for-inits-word-never-wakes-once-the-stream-is-dead.md b/issues/build/wait-until-for-the-supervisors-word-never-wakes-once-the-stream-is-dead.md similarity index 100% rename from issues/build/wait-until-for-inits-word-never-wakes-once-the-stream-is-dead.md rename to issues/build/wait-until-for-the-supervisors-word-never-wakes-once-the-stream-is-dead.md diff --git a/issues/design-debt/a-netd-client-cannot-tell-a-reset-from-the-peers-fin.md b/issues/design-debt/a-netstack-client-cannot-tell-a-reset-from-the-peers-fin.md similarity index 100% rename from issues/design-debt/a-netd-client-cannot-tell-a-reset-from-the-peers-fin.md rename to issues/design-debt/a-netstack-client-cannot-tell-a-reset-from-the-peers-fin.md diff --git a/issues/design-debt/connects-are-turned-away-for-6-s-after-logd-listens-again.md b/issues/design-debt/connects-are-turned-away-for-6-s-after-logkeeper-listens-again.md similarity index 100% rename from issues/design-debt/connects-are-turned-away-for-6-s-after-logd-listens-again.md rename to issues/design-debt/connects-are-turned-away-for-6-s-after-logkeeper-listens-again.md diff --git a/issues/design-debt/blockd-ships-a-staging-flag.md b/issues/design-debt/diskserver-ships-a-staging-flag.md similarity index 100% rename from issues/design-debt/blockd-ships-a-staging-flag.md rename to issues/design-debt/diskserver-ships-a-staging-flag.md diff --git a/issues/design-debt/getsockname-answers-an-address-nobody-asked-netd-for.md b/issues/design-debt/getsockname-answers-an-address-nobody-asked-netstack-for.md similarity index 100% rename from issues/design-debt/getsockname-answers-an-address-nobody-asked-netd-for.md rename to issues/design-debt/getsockname-answers-an-address-nobody-asked-netstack-for.md diff --git a/issues/design-debt/netd-holds-a-pending-request-for-a-client-that-left.md b/issues/design-debt/netstack-holds-a-pending-request-for-a-client-that-left.md similarity index 100% rename from issues/design-debt/netd-holds-a-pending-request-for-a-client-that-left.md rename to issues/design-debt/netstack-holds-a-pending-request-for-a-client-that-left.md diff --git a/issues/design-debt/netd-keeps-receiving-for-a-client-that-closed-its-receive-end.md b/issues/design-debt/netstack-keeps-receiving-for-a-client-that-closed-its-receive-end.md similarity index 100% rename from issues/design-debt/netd-keeps-receiving-for-a-client-that-closed-its-receive-end.md rename to issues/design-debt/netstack-keeps-receiving-for-a-client-that-closed-its-receive-end.md diff --git a/issues/design-debt/netd-lookup-slots-have-no-per-client-share.md b/issues/design-debt/netstack-lookup-slots-have-no-per-client-share.md similarity index 100% rename from issues/design-debt/netd-lookup-slots-have-no-per-client-share.md rename to issues/design-debt/netstack-lookup-slots-have-no-per-client-share.md diff --git a/issues/design-debt/netd-passes-every-millisecond-while-a-request-is-pending.md b/issues/design-debt/netstack-passes-every-millisecond-while-a-request-is-pending.md similarity index 100% rename from issues/design-debt/netd-passes-every-millisecond-while-a-request-is-pending.md rename to issues/design-debt/netstack-passes-every-millisecond-while-a-request-is-pending.md diff --git a/issues/design-debt/netd-resolver-asks-a-dead-primary-first-on-every-lookup.md b/issues/design-debt/netstack-resolver-asks-a-dead-primary-first-on-every-lookup.md similarity index 100% rename from issues/design-debt/netd-resolver-asks-a-dead-primary-first-on-every-lookup.md rename to issues/design-debt/netstack-resolver-asks-a-dead-primary-first-on-every-lookup.md diff --git a/issues/design-debt/netd-spends-two-poller-slots-per-piped-connection.md b/issues/design-debt/netstack-spends-two-poller-slots-per-piped-connection.md similarity index 100% rename from issues/design-debt/netd-spends-two-poller-slots-per-piped-connection.md rename to issues/design-debt/netstack-spends-two-poller-slots-per-piped-connection.md diff --git a/issues/design-debt/toybox-net-cannot-reach-netd.md b/issues/design-debt/toybox-net-cannot-reach-netstack.md similarity index 100% rename from issues/design-debt/toybox-net-cannot-reach-netd.md rename to issues/design-debt/toybox-net-cannot-reach-netstack.md diff --git a/issues/design-debt/toyos-has-its-own-network-stack.md b/issues/design-debt/toyos-has-its-own-network-stack.md index f49c8538c4b..173979678ca 100644 --- a/issues/design-debt/toyos-has-its-own-network-stack.md +++ b/issues/design-debt/toyos-has-its-own-network-stack.md @@ -16,7 +16,7 @@ netd runs smoltcp. Its replacement is ToyOS's own stack, built clean-room: reade - Stage 5: netd on one shard, pipe ABI unchanged; smoltcp leaves netd, `Cargo.toml` and `userland/Cargo.lock` in the same PR. - Then multi-core, netring (blocked on the owner's ABI ruling), TCP and IP hardening, IPv6, offloads, soak. -The listener defects are this track's: `issues/hardware/a-handshake-nobody-finishes-holds-a-listeners-port-shut.md` and `issues/hardware/a-connect-between-two-accepts-is-reset.md`, on smoltcp until stage 5, and `issues/hardware/an-accept-that-never-reaches-netd-strands-its-listener.md`, in std's accept. +The listener defects are this track's: `issues/hardware/a-handshake-nobody-finishes-holds-a-listeners-port-shut.md` and `issues/hardware/a-connect-between-two-accepts-is-reset.md`, on smoltcp until stage 5, and `issues/hardware/an-accept-that-never-reaches-netstack-strands-its-listener.md`, in std's accept. Owed from the stage 3 specifications: US-57 by stage 5, whose netd maps UDP's refusals onto the pipe ABI; `dhcp.renew-unroutable` by stage 5, whose netd counts it where `toyos-net-udp` refuses the renewal `udp.no-route`; FRA-01–20 and PMTU-01–06 by IP hardening. diff --git a/issues/diagnostics/a-netd-that-dies-while-serving-leaves-the-hosts-stream-silent.md b/issues/diagnostics/a-netstack-that-dies-while-serving-leaves-the-hosts-stream-silent.md similarity index 100% rename from issues/diagnostics/a-netd-that-dies-while-serving-leaves-the-hosts-stream-silent.md rename to issues/diagnostics/a-netstack-that-dies-while-serving-leaves-the-hosts-stream-silent.md diff --git a/issues/diagnostics/netds-lease-probe-answers-a-question-its-lines-already-answer.md b/issues/diagnostics/netstacks-lease-probe-answers-a-question-its-lines-already-answer.md similarity index 100% rename from issues/diagnostics/netds-lease-probe-answers-a-question-its-lines-already-answer.md rename to issues/diagnostics/netstacks-lease-probe-answers-a-question-its-lines-already-answer.md diff --git a/issues/diagnostics/netds-transmit-drop-report-cadence-has-no-deterministic-test.md b/issues/diagnostics/netstacks-transmit-drop-report-cadence-has-no-deterministic-test.md similarity index 100% rename from issues/diagnostics/netds-transmit-drop-report-cadence-has-no-deterministic-test.md rename to issues/diagnostics/netstacks-transmit-drop-report-cadence-has-no-deterministic-test.md diff --git a/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md b/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md index b60c3078669..9522e85abcd 100644 --- a/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md +++ b/issues/diagnostics/nothing-in-the-machine-can-read-the-trace-ring.md @@ -32,7 +32,7 @@ work then stops and is judged before anything more is built on it. trace. A window's record names its opener by address, which `issues/kernel/the-cpu-that-spawns-a-toybox-applet-reads-1-4-ms-of-interrupts-and-preemption-off-on-the-t14.md` and - `issues/kernel/inits-claim-of-a-pci-function-the-t14-lacks-holds-interrupts-off-for-3-8-ms.md` + `issues/kernel/the-supervisors-claim-of-a-pci-function-the-t14-lacks-holds-interrupts-off-for-3-8-ms.md` need. Behind that judgement, and not before it: interrupt enter and exit records diff --git a/issues/diagnostics/toyos-records-carry-the-sticks-serial-the-cards-mac-and-the-resolvers-in-full.md b/issues/diagnostics/toyos-records-carry-the-sticks-serial-the-cards-mac-and-the-resolvers-in-full.md index 45ad5308518..2cd65e695d9 100644 --- a/issues/diagnostics/toyos-records-carry-the-sticks-serial-the-cards-mac-and-the-resolvers-in-full.md +++ b/issues/diagnostics/toyos-records-carry-the-sticks-serial-the-cards-mac-and-the-resolvers-in-full.md @@ -13,11 +13,11 @@ public carries them unless whoever pastes it masks them by hand: - the USB stick's serial number: `kernel/src/drivers/xhci/wait/msc.rs:1407`, on every bind, and `:1415`, when a disk comes back; -- the network card's MAC: `userland/netd/src/main.rs:1608`, and +- the network card's MAC: `userland/netstack/src/main.rs:1605`, and `src/metal.rs:2281`, where the host loop writes the one it read before the flash into the readback's `boot.txt`; - the resolvers the lease named, which on the bench are the provider's public - ones: `userland/netd/src/dhcp.rs:149`. + ones: `userland/netstack/src/dhcp.rs:149`. `src/sourcegate.rs` reads tracked files only. A pull request's body, a comment and a commit message are read by nothing before they are public. diff --git a/issues/filesystem/a-renamed-services-state-stays-under-its-old-name-unread.md b/issues/filesystem/a-renamed-services-state-stays-under-its-old-name-unread.md new file mode 100644 index 00000000000..136844db04c --- /dev/null +++ b/issues/filesystem/a-renamed-services-state-stays-under-its-old-name-unread.md @@ -0,0 +1,40 @@ +--- +status: open +kind: defect +opened: 2026-10-03 +--- + +# A renamed service's state stays under its old name, unread + +The supervisor starts a service with `HOME` at `/state/` +(`toyos-manifest`'s `home`), so a service's state is keyed by its program's +name and a rename orphans it with nothing said. Stage 1 of +`issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md` renamed +five services, and a DATA volume that outlives that change: + +- keeps `/state/logd`, `/state/soundd`, `/state/netd`, `/state/sshd` and + `/state/blockd`, which nothing reads or deletes; +- answers ssh with a host key `sshserver` mints afresh under + `/state/sshserver`, which a client that pinned the old key refuses; +- no longer authorizes a key that lived only in `/state/sshd/authorized_keys`: + `userland/sshserver/src/main.rs`'s `authorized_keys` reads + `/state/sshserver/authorized_keys` and `/system/etc/ssh_authorized_keys`, so + a machine updated over ssh whose owner's key was only there refuses its owner + afterwards. + +A package under `/apps` built before the rename asks `toyos::endow::service` +for `soundd` and `netd`, which no row endows, so it finds no sound or network +server until it is reinstalled. + +A DATA outlives an image only where one was made to: the boot image carries +none (`src/image.rs`'s `create_boot_image`), and the build stamps the +designation the kernel formats only into a scratch file it has just created +(`src/build.rs`'s `create_sparse`). Every checkout's `target/nvme.img`, which +`cargo run` keeps across runs, is one; a machine holds one only where a stamped +TOYOS-DATA partition was put by hand, and whether any of the owner's does is +not known here. + +**Owner**: the orchestrator, which holds the supervisor track above. + +**Exit**: the supervisor names at boot every `/state` directory that no service +of the running manifest owns, and a test stages one and reads the line. diff --git a/issues/filesystem/blockd-resets-a-drive-that-is-slow-and-healthy.md b/issues/filesystem/diskserver-resets-a-drive-that-is-slow-and-healthy.md similarity index 100% rename from issues/filesystem/blockd-resets-a-drive-that-is-slow-and-healthy.md rename to issues/filesystem/diskserver-resets-a-drive-that-is-slow-and-healthy.md diff --git a/issues/filesystem/blockd-serves-the-slot-the-machine-runs-from.md b/issues/filesystem/diskserver-serves-the-slot-the-machine-runs-from.md similarity index 100% rename from issues/filesystem/blockd-serves-the-slot-the-machine-runs-from.md rename to issues/filesystem/diskserver-serves-the-slot-the-machine-runs-from.md diff --git a/issues/filesystem/logd-flushes-the-records-its-own-refused-flush-made.md b/issues/filesystem/logkeeper-flushes-the-records-its-own-refused-flush-made.md similarity index 100% rename from issues/filesystem/logd-flushes-the-records-its-own-refused-flush-made.md rename to issues/filesystem/logkeeper-flushes-the-records-its-own-refused-flush-made.md diff --git a/issues/filesystem/logd-still-says-a-budget-refusal-leaves-the-device-untouched.md b/issues/filesystem/logkeeper-still-says-a-budget-refusal-leaves-the-device-untouched.md similarity index 100% rename from issues/filesystem/logd-still-says-a-budget-refusal-leaves-the-device-untouched.md rename to issues/filesystem/logkeeper-still-says-a-budget-refusal-leaves-the-device-untouched.md diff --git a/issues/filesystem/nothing-reopens-a-blockd-session-over-a-used-page.md b/issues/filesystem/nothing-reopens-a-diskserver-session-over-a-used-page.md similarity index 100% rename from issues/filesystem/nothing-reopens-a-blockd-session-over-a-used-page.md rename to issues/filesystem/nothing-reopens-a-diskserver-session-over-a-used-page.md diff --git a/issues/filesystem/one-blockd-session-can-hold-every-device-slot.md b/issues/filesystem/one-diskserver-session-can-hold-every-device-slot.md similarity index 100% rename from issues/filesystem/one-blockd-session-can-hold-every-device-slot.md rename to issues/filesystem/one-diskserver-session-can-hold-every-device-slot.md diff --git a/issues/filesystem/the-logs-server-ending-under-logds-append-is-unmeasured.md b/issues/filesystem/the-logs-server-ending-under-logkeepers-append-is-unmeasured.md similarity index 100% rename from issues/filesystem/the-logs-server-ending-under-logds-append-is-unmeasured.md rename to issues/filesystem/the-logs-server-ending-under-logkeepers-append-is-unmeasured.md diff --git a/issues/filesystem/where-everything-lives.md b/issues/filesystem/where-everything-lives.md index 2dc667a356a..9fa3b2de22f 100644 --- a/issues/filesystem/where-everything-lives.md +++ b/issues/filesystem/where-everything-lives.md @@ -117,4 +117,4 @@ until that lands nothing verifies it. `--exit-with-lease` bench report the metal loop reads off the stick's FAT log volume, as it reads `/log/metal-*.bin`, and the DATA volume is not readable there. It goes with -`issues/diagnostics/netds-lease-probe-answers-a-question-its-lines-already-answer.md`. +`issues/diagnostics/netstacks-lease-probe-answers-a-question-its-lines-already-answer.md`. diff --git a/issues/hardware/a-replacement-netd-reuses-its-predecessors-ports.md b/issues/hardware/a-replacement-netstack-reuses-its-predecessors-ports.md similarity index 100% rename from issues/hardware/a-replacement-netd-reuses-its-predecessors-ports.md rename to issues/hardware/a-replacement-netstack-reuses-its-predecessors-ports.md diff --git a/issues/hardware/an-accept-that-never-reaches-netd-strands-its-listener.md b/issues/hardware/an-accept-that-never-reaches-netstack-strands-its-listener.md similarity index 100% rename from issues/hardware/an-accept-that-never-reaches-netd-strands-its-listener.md rename to issues/hardware/an-accept-that-never-reaches-netstack-strands-its-listener.md diff --git a/issues/hardware/blockd-drives-nvme-apst.md b/issues/hardware/diskserver-drives-nvme-apst.md similarity index 100% rename from issues/hardware/blockd-drives-nvme-apst.md rename to issues/hardware/diskserver-drives-nvme-apst.md diff --git a/issues/hardware/metalprobes-usb-read-is-answered-from-fsds-cache.md b/issues/hardware/metalprobes-usb-read-is-answered-from-fileservers-cache.md similarity index 100% rename from issues/hardware/metalprobes-usb-read-is-answered-from-fsds-cache.md rename to issues/hardware/metalprobes-usb-read-is-answered-from-fileservers-cache.md diff --git a/issues/hardware/netd-refused-accept-hung-waiting-for-a-wake-that-never-came.md b/issues/hardware/netstack-refused-accept-hung-waiting-for-a-wake-that-never-came.md similarity index 100% rename from issues/hardware/netd-refused-accept-hung-waiting-for-a-wake-that-never-came.md rename to issues/hardware/netstack-refused-accept-hung-waiting-for-a-wake-that-never-came.md diff --git a/issues/hardware/netd-removes-a-closed-stream-before-its-fin-leaves.md b/issues/hardware/netstack-removes-a-closed-stream-before-its-fin-leaves.md similarity index 100% rename from issues/hardware/netd-removes-a-closed-stream-before-its-fin-leaves.md rename to issues/hardware/netstack-removes-a-closed-stream-before-its-fin-leaves.md diff --git a/issues/hardware/netds-i219-drops-a-transmit-burst-past-its-ring.md b/issues/hardware/netstacks-i219-drops-a-transmit-burst-past-its-ring.md similarity index 100% rename from issues/hardware/netds-i219-drops-a-transmit-burst-past-its-ring.md rename to issues/hardware/netstacks-i219-drops-a-transmit-burst-past-its-ring.md diff --git a/issues/hardware/the-t14-reboots-through-ubuntu-for-every-test.md b/issues/hardware/the-t14-reboots-through-ubuntu-for-every-test.md index 66dae43deb7..80ddaf9abd4 100644 --- a/issues/hardware/the-t14-reboots-through-ubuntu-for-every-test.md +++ b/issues/hardware/the-t14-reboots-through-ubuntu-for-every-test.md @@ -18,7 +18,7 @@ metal rows. wedge, a reset) or judges a boot (the loader, an update, a file read back after a reboot). Its registration says which. - **One exec channel**, to `test-runner`'s stdin loop, since `sshd` aliases a - second channel's input (`issues/isolation/sshd-holds-one-channel-and-does-not-say-so.md`). + second channel's input (`issues/isolation/sshserver-holds-one-channel-and-does-not-say-so.md`). `tests/ssh-client-host`'s `pipe` relays it once it writes output as it arrives (`tests/ssh-client-host/src/main.rs:251-263`). - **A test's window** is what crosses between its markers: the job's output, diff --git a/issues/isolation/a-file-server-can-open-every-partition-blockd-serves.md b/issues/isolation/a-file-server-can-open-every-partition-diskserver-serves.md similarity index 100% rename from issues/isolation/a-file-server-can-open-every-partition-blockd-serves.md rename to issues/isolation/a-file-server-can-open-every-partition-diskserver-serves.md diff --git a/issues/isolation/a-second-launch-of-a-serves-program-panics-init.md b/issues/isolation/a-second-launch-of-a-serves-program-panics-the-supervisor.md similarity index 100% rename from issues/isolation/a-second-launch-of-a-serves-program-panics-init.md rename to issues/isolation/a-second-launch-of-a-serves-program-panics-the-supervisor.md diff --git a/issues/isolation/every-program-sees-only-the-files-it-was-given.md b/issues/isolation/every-program-sees-only-the-files-it-was-given.md index 50c155aa9a2..25a65f939bd 100644 --- a/issues/isolation/every-program-sees-only-the-files-it-was-given.md +++ b/issues/isolation/every-program-sees-only-the-files-it-was-given.md @@ -11,7 +11,7 @@ longer the declared exception to the capability model. This reverses question 2 of `issues/kernel/the-capability-end-state-is-twelve-answers.md`. Today any process opens, deletes or spawns any path, so there is no boundary between two programs, let alone between two people: any process can append a line to -sshd's key list and log in remotely (`issues/isolation/sshd-authorized-keys-unprotected.md`). +sshd's key list and log in remotely (`issues/isolation/sshserver-authorized-keys-unprotected.md`). ## The model diff --git a/issues/isolation/netd-socket-ids-are-ambient.md b/issues/isolation/netstack-socket-ids-are-ambient.md similarity index 100% rename from issues/isolation/netd-socket-ids-are-ambient.md rename to issues/isolation/netstack-socket-ids-are-ambient.md diff --git a/issues/isolation/sshd-authorized-keys-unprotected.md b/issues/isolation/sshserver-authorized-keys-unprotected.md similarity index 100% rename from issues/isolation/sshd-authorized-keys-unprotected.md rename to issues/isolation/sshserver-authorized-keys-unprotected.md diff --git a/issues/isolation/sshd-holds-one-channel-and-does-not-say-so.md b/issues/isolation/sshserver-holds-one-channel-and-does-not-say-so.md similarity index 100% rename from issues/isolation/sshd-holds-one-channel-and-does-not-say-so.md rename to issues/isolation/sshserver-holds-one-channel-and-does-not-say-so.md diff --git a/issues/isolation/sshd-still-speaks-rsa.md b/issues/isolation/sshserver-still-speaks-rsa.md similarity index 100% rename from issues/isolation/sshd-still-speaks-rsa.md rename to issues/isolation/sshserver-still-speaks-rsa.md diff --git a/issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md b/issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md index a342ceb7b2d..d10b0f03766 100644 --- a/issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md +++ b/issues/isolation/the-supervisor-is-host-tested-and-owns-the-stop.md @@ -6,8 +6,7 @@ opened: 2026-09-28 # The supervisor is host-tested and owns the machine's stop -Held by the orchestrator. Stage 1 lands right after #592 and #631, of which -#631 has landed, before the latency work +Held by the orchestrator. Stage 1 landed before the latency work (`issues/kernel/toyos-beats-linuxs-latency-on-the-t14.md`; owner, 2026-10-03). ## Stages @@ -15,10 +14,12 @@ Held by the orchestrator. Stage 1 lands right after #592 and #631, of which Every guest test this track names is registered. A deleted test covers nothing. -1. **The rename**, one mechanical PR. Before stage 1 is - briefed, the exit's search below runs once over the `rust/` fork's delta as - well as the superproject, so its hits are known going in. It touches `toyos/src`, - `toyos-abi/src`, `userland/libc/src` and the `rust/` fork's delta, and its +1. **Done. The rename**, one mechanical PR. Before stage 1 is + briefed, the exit's search below runs once over the `rust/` fork's delta and + the delta of every fork a lockfile pins as well as the superproject, so its + hits are known going in. It touches `toyos/src`, `toyos-abi/src`, + `userland/libc/src` and the `rust/`, `mio`, `socket2`, `cpal` and `tokio` + forks' deltas, and its `CLAUDE.md` edits are placed in the same PR by an agent briefed for them. Issue slugs carrying an old name are renamed with every citation. @@ -35,8 +36,8 @@ nothing. | `compositor` | unchanged | **Exit**: over every tracked path and every text file's content, in the - superproject and the `rust/` fork's delta, - excluding the bodies of `issues/` files (recorded evidence), no hit remains + superproject, the `rust/` fork's delta and the delta of every fork a + lockfile pins, excluding the bodies of `issues/` files (recorded evidence), no hit remains outside the exclusions, each judged per match and not per line: - a case-insensitive substring search for `netd`, `logd`, `soundd`, `blockd`, `fsd`, `sshd`, excluding, case-insensitively, an identifier diff --git a/issues/kernel/a-held-disk-waits-for-a-pass-no-cpu-takes-when-every-cpu-is-in-a-call-on-it.md b/issues/kernel/a-held-disk-waits-for-a-pass-no-cpu-takes-when-every-cpu-is-in-a-call-on-it.md index 570f67e7822..a72ef1038a8 100644 --- a/issues/kernel/a-held-disk-waits-for-a-pass-no-cpu-takes-when-every-cpu-is-in-a-call-on-it.md +++ b/issues/kernel/a-held-disk-waits-for-a-pass-no-cpu-takes-when-every-cpu-is-in-a-call-on-it.md @@ -44,7 +44,7 @@ reboot's sync and cpu1 in a shootdown **What is still wrong**: the operation that waited answers `BudgetExpired` instead of the device's answer, and a caller that gives up on one — `logd` on a -refused create (`issues/boot-media/logd-ends-the-boots-log-on-one-refused-create-and-nothing-durable-says-so.md`) +refused create (`issues/boot-media/logkeeper-ends-the-boots-log-on-one-refused-create-and-nothing-durable-says-so.md`) — loses what it was doing. The retry loops above the block layer spin with `IF` clear too, so on a machine with one CPU the device binds only when the caller leaves the kernel. diff --git a/issues/kernel/a-log-rings-owner-is-named-only-when-logd-reads-its-registration.md b/issues/kernel/a-log-rings-owner-is-named-only-when-logkeeper-reads-its-registration.md similarity index 100% rename from issues/kernel/a-log-rings-owner-is-named-only-when-logd-reads-its-registration.md rename to issues/kernel/a-log-rings-owner-is-named-only-when-logkeeper-reads-its-registration.md diff --git a/issues/kernel/netd-answers-for-its-name-without-claiming-it.md b/issues/kernel/netstack-answers-for-its-name-without-claiming-it.md similarity index 100% rename from issues/kernel/netd-answers-for-its-name-without-claiming-it.md rename to issues/kernel/netstack-answers-for-its-name-without-claiming-it.md diff --git a/issues/kernel/soundd-past-due-wake-max-1.md b/issues/kernel/soundserver-past-due-wake-max-1.md similarity index 100% rename from issues/kernel/soundd-past-due-wake-max-1.md rename to issues/kernel/soundserver-past-due-wake-max-1.md diff --git a/issues/kernel/storage-still-comes-up-before-init-runs.md b/issues/kernel/storage-still-comes-up-before-the-supervisor-runs.md similarity index 100% rename from issues/kernel/storage-still-comes-up-before-init-runs.md rename to issues/kernel/storage-still-comes-up-before-the-supervisor-runs.md diff --git a/issues/kernel/inits-claim-of-a-pci-function-the-t14-lacks-holds-interrupts-off-for-3-8-ms.md b/issues/kernel/the-supervisors-claim-of-a-pci-function-the-t14-lacks-holds-interrupts-off-for-3-8-ms.md similarity index 100% rename from issues/kernel/inits-claim-of-a-pci-function-the-t14-lacks-holds-interrupts-off-for-3-8-ms.md rename to issues/kernel/the-supervisors-claim-of-a-pci-function-the-t14-lacks-holds-interrupts-off-for-3-8-ms.md diff --git a/issues/kernel/toyos-uses-what-modern-hardware-offers-for-speed.md b/issues/kernel/toyos-uses-what-modern-hardware-offers-for-speed.md index e0994691323..56bcf545a65 100644 --- a/issues/kernel/toyos-uses-what-modern-hardware-offers-for-speed.md +++ b/issues/kernel/toyos-uses-what-modern-hardware-offers-for-speed.md @@ -29,4 +29,4 @@ if it beats ToyOS without it. What no proving machine is known to offer is - `issues/kernel/a-tlb-shootdown-reaches-only-the-cpus-that-ran-the-space.md` - `issues/kernel/fsgsbase-is-measured-then-taken-or-rejected.md` - `issues/kernel/idle-cpus-enter-the-c-states-cst-names.md` -- `issues/hardware/blockd-drives-nvme-apst.md` +- `issues/hardware/diskserver-drives-nvme-apst.md` diff --git a/kernel/src/arch/x86_64/idt/mod.rs b/kernel/src/arch/x86_64/idt/mod.rs index f5ed027ec4f..c6ae1ff6081 100644 --- a/kernel/src/arch/x86_64/idt/mod.rs +++ b/kernel/src/arch/x86_64/idt/mod.rs @@ -256,7 +256,6 @@ idt_vectors! { ring0 Nmi = 0x02, nmi::nmi_entry, ist 2; ring3 Timer = 0x20, timer::timer_entry; ring3 Xhci = 0x21, xhci::xhci_entry; - // 0x22 was the kernel's own virtio-net driver, which now lives in netd. ring3 VirtioSound = 0x23, virtio_sound::virtio_sound_entry; ring3 I8042 = 0x24, i8042::i8042_entry; ring3 DmaFault = 0x25, dma_fault::dma_fault_entry; diff --git a/kernel/src/arch/x86_64/watchdog.rs b/kernel/src/arch/x86_64/watchdog.rs index 3dec12a4ff0..719be5ab72d 100644 --- a/kernel/src/arch/x86_64/watchdog.rs +++ b/kernel/src/arch/x86_64/watchdog.rs @@ -1,7 +1,7 @@ //! The chipset's TCO watchdog, armed on request and fed from the scheduler //! pass — the one function an idle CPU and a busy one both run every trip, so //! **what it proves alive is that some CPU still reaches it**. A panicked -//! machine is reset by the same bound, which is the loop's recovery: logd is +//! machine is reset by the same bound, which is the loop's recovery: logkeeper is //! dead after a kernel panic, so nothing more could be made durable anyway. use core::sync::atomic::{AtomicU16, AtomicU64, Ordering}; diff --git a/kernel/src/bcachefs_adapter.rs b/kernel/src/bcachefs_adapter.rs index ae40cf98b62..94ff0fc2be1 100644 --- a/kernel/src/bcachefs_adapter.rs +++ b/kernel/src/bcachefs_adapter.rs @@ -1,6 +1,6 @@ //! ROOT as the VFS reads it: the signed image, a read-only bcachefs volume in //! memory. The only filesystem this kernel mounts; every writable one is a -//! file server's (`/system/bin/fsd`). +//! file server's (`/system/bin/fileserver`). use alloc::collections::BTreeMap; use alloc::string::String; diff --git a/kernel/src/drivers/hda.rs b/kernel/src/drivers/hda.rs index d86471b818d..ff65cef757b 100644 --- a/kernel/src/drivers/hda.rs +++ b/kernel/src/drivers/hda.rs @@ -3,7 +3,7 @@ //! The kernel touches only registers whose value is an address, indexes a //! kernel structure, or acknowledges the interrupt; everything else a driver //! reaches goes through [`reg_write`] and [`reg_read`], gated by a positive -//! list and refused by name. Codec and pin decisions belong to soundd, never +//! list and refused by name. Codec and pin decisions belong to soundserver, never //! to this file. use core::cell::UnsafeCell; @@ -80,7 +80,7 @@ const SD_STS_WRITE_CLEAR: u8 = SD_STS_BCIS | SD_STS_FIFOE | SD_STS_DESE; const PERIODS: usize = 8; const PERIOD_BYTES: usize = 512; -/// The tag this stream carries; [`HdaInfo::stream_tag`] is how soundd's verb names the same number. +/// The tag this stream carries; [`HdaInfo::stream_tag`] is how soundserver's verb names the same number. const STREAM_TAG: u8 = 1; /// The smallest register window that can hold a stream descriptor; a BAR under this is refused. diff --git a/kernel/src/drivers/panic_console/mod.rs b/kernel/src/drivers/panic_console/mod.rs index 2228210d661..89a2cafdc21 100644 --- a/kernel/src/drivers/panic_console/mod.rs +++ b/kernel/src/drivers/panic_console/mod.rs @@ -2,7 +2,7 @@ //! //! Renders log records as an 8x16 text grid onto the UEFI GOP framebuffer, //! through `LogRecord`'s `Display`, so no second formatter can drift from -//! `logd`. [`capture`] freezes the report before `panic_flush` drains it; +//! `logkeeper`. [`capture`] freezes the report before `panic_flush` drains it; //! [`render`] paints it inside `halt_all_cpus`, before `panic_flush`. virtio-gpu //! is unsupported: its scanout needs the unbounded-poll wedge this module avoids. //! @@ -1000,7 +1000,7 @@ const CENSUS: &str = "panel: paints="; /// One line, written to the two channels a boot can end on: [`log_census`] for /// a boot that hands the machine back, and [`seal_wedge`] for one a bound ends -/// with no `logd` left to write a file. +/// with no `logkeeper` left to write a file. struct Census; impl core::fmt::Display for Census { diff --git a/kernel/src/drivers/serial.rs b/kernel/src/drivers/serial.rs index 67368b2d52a..111358ad6cd 100644 --- a/kernel/src/drivers/serial.rs +++ b/kernel/src/drivers/serial.rs @@ -354,7 +354,7 @@ fn uart_write_fifo(bytes: &[u8]) { /// `klogd`'s queue ([`crate::log::console::queue`]), and `klogd` puts it on /// the wire between its own records — so the kernel has one console writer, /// and a write here never waits on a device. The bytes go as they came: the -/// only holder that writes is `/system/bin/logd`, which renders every control +/// only holder that writes is `/system/bin/logkeeper`, which renders every control /// byte a program wrote as text before it gets here. /// /// **A write takes the whole lines the queue has room for and no more**, and diff --git a/kernel/src/drivers/virtio_sound.rs b/kernel/src/drivers/virtio_sound.rs index c5cf09e9d47..449c82d5660 100644 --- a/kernel/src/drivers/virtio_sound.rs +++ b/kernel/src/drivers/virtio_sound.rs @@ -3,7 +3,7 @@ //! Every DMA address lives in the descriptor tables, built once at bind from //! kernel-allocated offsets; after bind the driver's whole vocabulary is an //! avail-ring index and a doorbell write. Stream selection, format and timing -//! are soundd's, not this driver's. +//! are soundserver's, not this driver's. //! //! Structure layouts and command codes follow VirtIO 1.2 §5.14. @@ -116,7 +116,7 @@ pub fn isr_complete() { const RECORD_RING_CAP: u32 = 16; /// SPSC: producer is the MSI-X handler (single CPU, IF=0); consumer holds [`CONTROLLER`]. -/// One record per interrupt, never accumulated — a folded mask would misreport lateness to soundd's DLL. +/// One record per interrupt, never accumulated — a folded mask would misreport lateness to soundserver's DLL. struct RecordRing { slots: [UnsafeCell; RECORD_RING_CAP as usize], head: AtomicU32, diff --git a/kernel/src/drivers/xhci/mod.rs b/kernel/src/drivers/xhci/mod.rs index e7b97ef8d96..4b65b0e21f0 100644 --- a/kernel/src/drivers/xhci/mod.rs +++ b/kernel/src/drivers/xhci/mod.rs @@ -1542,7 +1542,7 @@ const BARRIER: crate::time::Duration = /// either way and the account says which of the two it was. /// /// Called from the shutdown path only, and after the log volume's last byte is -/// durable — before that, `logd` still has that volume to write. +/// durable — before that, `logkeeper` still has that volume to write. pub fn seal_shut() { match take_within(BARRIER.nanos()) { Some(guard) => { diff --git a/kernel/src/drivers/xhci/wait/msc.rs b/kernel/src/drivers/xhci/wait/msc.rs index 8912ddf5157..aca75bcff1a 100644 --- a/kernel/src/drivers/xhci/wait/msc.rs +++ b/kernel/src/drivers/xhci/wait/msc.rs @@ -429,7 +429,7 @@ impl XhciController { // CODE once answers it every time, and issuing anyway costs a full // Bulk-Only round trip plus a REQUEST SENSE — under `XHCI`, with // preemption off, on the device the log is going to — for every - // `logd` batch on a stick like the T14's. + // `logkeeper` batch on a stick like the T14's. if dev.no_write_cache { return Ok(()); } diff --git a/kernel/src/loader/mod.rs b/kernel/src/loader/mod.rs index df9809060e7..277442a54bc 100644 --- a/kernel/src/loader/mod.rs +++ b/kernel/src/loader/mod.rs @@ -852,14 +852,14 @@ fn apply_tls_relocs( /// The one program the kernel starts. `src/build.rs` puts this binary in every /// image, so a missing one is a bad build, not a different boot. -pub const INIT_PATH: &str = "/system/bin/init"; +pub const SUPERVISOR_PATH: &str = "/system/bin/supervisor"; -/// Start `/system/bin/init`, holding the machine's one full-rights `SysCap`. +/// Start `/system/bin/supervisor`, holding the machine's one full-rights `SysCap`. /// -/// Nothing else can construct one: what init endows is the entire set of +/// Nothing else can construct one: what the supervisor endows is the entire set of /// processes that can ever claim a device, enter the RT band, or power off. -/// Panics on failure: a boot that cannot start init has nowhere to report to. -pub fn spawn_init() -> Pid { +/// Panics on failure: a boot that cannot start the supervisor has nowhere to report to. +pub fn spawn_supervisor() -> Pid { let mut handles = HandleTable::new(); let console = KObjectRef::Console(crate::object::device::ConsoleObject::new()); for slot in 0..3 { @@ -869,7 +869,7 @@ pub fn spawn_init() -> Pid { ); let (_, displaced) = handles .install_at(slot, entry) - .expect("spawn_init: three slots cannot exhaust an empty table"); + .expect("spawn_supervisor: three slots cannot exhaust an empty table"); assert!(displaced.is_none(), "an empty table had something at slot {slot}"); } let cap = KObjectRef::SysCap(crate::object::syscap::SysCap::new()); @@ -888,7 +888,7 @@ pub fn spawn_init() -> Pid { .union(Rights::INVENTORY); let cap_handle = handles .install(crate::object::HandleEntry::new(cap, rights)) - .expect("spawn_init: an empty table refused the system capability"); + .expect("spawn_supervisor: an empty table refused the system capability"); let label = toyos_abi::syscall::SYSCAP_LABEL; let mut entries = alloc::vec![toyos_abi::syscall::EndowEntry { label_off: 0, @@ -897,14 +897,14 @@ pub fn spawn_init() -> Pid { _pad: 0, }]; let mut labels = label.as_bytes().to_vec(); - // Built by the kernel and owing nobody anything: no table but init's own holds it. + // Built by the kernel and owing nobody anything: no table but the supervisor's own holds it. let commit = |own| { start::endow_self(&mut handles, &mut entries, &mut labels, own); Ok((handles, Endowments::new(entries, labels), ())) }; - match spawn(&[INIT_PATH], commit, String::from("/"), Vec::new(), None, Parent::Root) { + match spawn(&[SUPERVISOR_PATH], commit, String::from("/"), Vec::new(), None, Parent::Root) { Ok((pid, ())) => pid, - Err(crate::object::Refusal::Error(e)) => panic!("spawn_init: failed to spawn: {e:?}"), - Err(crate::object::Refusal::Handle(e)) => panic!("spawn_init: {e}"), + Err(crate::object::Refusal::Error(e)) => panic!("spawn_supervisor: failed to spawn: {e:?}"), + Err(crate::object::Refusal::Handle(e)) => panic!("spawn_supervisor: {e}"), } } diff --git a/kernel/src/log/console.rs b/kernel/src/log/console.rs index 79213270791..4da55020424 100644 --- a/kernel/src/log/console.rs +++ b/kernel/src/log/console.rs @@ -3,7 +3,7 @@ //! //! **One writer.** `klogd` puts the kernel's records on the wire, and between //! them the lines console holders write ([`queue`]) — which on this machine is -//! `/system/bin/logd` alone, rendering each program's line with its tag. +//! `/system/bin/logkeeper` alone, rendering each program's line with its tag. //! It holds the wire ([`serial::wire`]) with interrupts on and //! preemption allowed, and the registers only for one burst at a time. //! @@ -31,7 +31,6 @@ use crate::sync::Lock; use super::read::{drain_ordered, Published, RecordSink}; use super::shard; -// klogd, not logd: `/system/bin/logd` is a separate userland process; one name for both would collide in a dump report. const NAME: &str = "klogd"; // `emit` finds `klogd` through this, not the process table: the lookup takes a lock, and `emit` runs inside IRQ handlers and every syscall's locked region. @@ -348,7 +347,7 @@ impl core::fmt::Write for Line { } } -/// Render one record as the console line; `logd`'s `/log` sink renders the same line with a different prefix. +/// Render one record as the console line; `logkeeper`'s `/log` sink renders the same line with a different prefix. pub fn write_line(record: &LogRecord, emit: impl FnMut(&[u8])) { use core::fmt::Write; let mut line = Line::new(emit); diff --git a/kernel/src/log/mod.rs b/kernel/src/log/mod.rs index 8899bd3f735..7dcea32f8e7 100644 --- a/kernel/src/log/mod.rs +++ b/kernel/src/log/mod.rs @@ -67,8 +67,8 @@ const TAIL_HEAD: &str = "log: this boot's newest records follow, newest first"; /// Seal the newest of this boot's records onto the black box, the one channel /// a boot's own tail has once the stop has begun. /// -/// **The kernel does not wait for `/system/bin/logd`, so it does not know what -/// reached `/log`.** `/system/bin/init` has `logd` flush before it asks for the +/// **The kernel does not wait for `/system/bin/logkeeper`, so it does not know what +/// reached `/log`.** `/system/bin/supervisor` has `logkeeper` flush before it asks for the /// stop; everything committed after that — the stop's own record, the last /// word — is on the console, and here, where the next /// loader pass prints it into `loader.log`. diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 66957505f97..5b38375ff06 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -194,7 +194,7 @@ fn report_power_on(args: &KernelArgs, complete: u64) { /// Says where this boot's log can be read, on the last surface still showing it once userland owns the screen. fn report_log_destination() { - // Kernel-side because panic_console owns the panel; logd reports which file it opened separately. + // Kernel-side because panic_console owns the panel; logkeeper reports which file it opened separately. // Whether the partition is on a disk this kernel reads, not whether its file server mounted it: // that server says so itself, and this kernel mounts nothing but ROOT. let console = drivers::serial::has_console(); @@ -448,7 +448,7 @@ pub(crate) unsafe extern "C" fn kernel_main(kernel_args: &KernelArgs) -> ! { } pipe::init(); - // ROOT is the loader's image in memory, so nothing from here to init's + // ROOT is the loader's image in memory, so nothing from here to the supervisor's // spawn asks a disk for anything: every storage driver comes up after it. use vfs::UserAccess; let root_fs = rootfs::mount(); @@ -461,18 +461,18 @@ pub(crate) unsafe extern "C" fn kernel_main(kernel_args: &KernelArgs) -> ! { boot_phase!("subsystems ready", t_subsys); - // init reads /system/etc/system.manifest itself; the boot config never names the program it starts. - let pid = process::spawn_init(); - log!("spawned {} pid={pid}", process::INIT_PATH); + // The supervisor reads /system/etc/system.manifest itself; the boot config never names the program it starts. + let pid = process::spawn_supervisor(); + log!("spawned {} pid={pid}", process::SUPERVISOR_PATH); - // The proof the boot up to here needed no disk: ROOT and init's image both + // The proof the boot up to here needed no disk: ROOT and the supervisor's image both // came out of memory. - log!("{} {}", rootfs::INIT_WITHOUT_A_DISK, block::census::commands_issued()); + log!("{} {}", rootfs::SUPERVISOR_WITHOUT_A_DISK, block::census::commands_issued()); - // After init's spawn and before it runs: nothing runs a task until + // After the supervisor's spawn and before it runs: nothing runs a task until // `smp::set_ready` below. This kernel mounts no disk: `/apps`, `/config`, - // `/home`, `/state`, `/log` and `/boot` are file servers' (`/system/bin/fsd`), - // and an NVMe controller is `/system/bin/blockd`'s. The USB disks are still + // `/home`, `/state`, `/log` and `/boot` are file servers' (`/system/bin/fileserver`), + // and an NVMe controller is `/system/bin/diskserver`'s. The USB disks are still // this kernel's, served to their file servers as partition claims, until // usbd drives the controller. let t_storage = clock::nanos_since_boot(); diff --git a/kernel/src/object/ops.rs b/kernel/src/object/ops.rs index 43b39373cc5..de9d68e653e 100644 --- a/kernel/src/object/ops.rs +++ b/kernel/src/object/ops.rs @@ -46,7 +46,7 @@ pub fn initial_rights(object: &KObjectRef) -> Rights { KObjectRef::Inbox(_) => { BASE.union(Rights::READ).union(Rights::WRITE).union(Rights::MAP) } - // Every `SysCap` bit is authority init decides per program: no default, the creator states it. + // Every `SysCap` bit is authority the supervisor decides per program: no default, the creator states it. KObjectRef::SysCap(_) => Rights::NONE, // `MAP` is the whole of it: a region is examined through the memory, not the handle. KObjectRef::SharedMem(_) => { diff --git a/kernel/src/object/syscap.rs b/kernel/src/object/syscap.rs index 6c0713ad14b..3a2f736e003 100644 --- a/kernel/src/object/syscap.rs +++ b/kernel/src/object/syscap.rs @@ -3,8 +3,8 @@ //! Minting a device claim, entering the RT band, and turning a pid into a //! process handle are each reachable only through one bit on a handle to //! this. The kernel creates exactly one full-rights `SysCap`, at boot, for -//! `/system/bin/init`; nothing else can construct one, so the set of processes -//! that can ever do the three is exactly what init endowed. +//! `/system/bin/supervisor`; nothing else can construct one, so the set of processes +//! that can ever do the three is exactly what the supervisor endowed. use alloc::sync::Arc; diff --git a/kernel/src/pcidev/mod.rs b/kernel/src/pcidev/mod.rs index 055419ae1c4..e87fb652658 100644 --- a/kernel/src/pcidev/mod.rs +++ b/kernel/src/pcidev/mod.rs @@ -82,7 +82,7 @@ //! **That rests on the next holder laying its grants out as the last one //! did.** The stale transfer — data and descriptor write-back — lands in //! whatever the new holder keeps at that address, after it has set up its own -//! rings or not: harmless for a netd succeeding a netd, a silent write into its +//! rings or not: harmless for a netstack succeeding a netstack, a silent write into its //! own memory for a holder with another layout. //! //! **A reset returns a function's configuration to its defaults, BARs diff --git a/kernel/src/pipe.rs b/kernel/src/pipe.rs index a879bf4e389..565679d4af3 100644 --- a/kernel/src/pipe.rs +++ b/kernel/src/pipe.rs @@ -151,7 +151,7 @@ impl Pipe { self.backing.as_mut() } - /// Republish "is the other end gone?" into the mapped header, for netd; the kernel itself decides from its own counts. + /// Republish "is the other end gone?" into the mapped header, for netstack; the kernel itself decides from its own counts. fn publish_ends(&mut self) { let Some(backing) = self.backing.as_mut() else { return }; if self.readers == 0 { backing.ring.close_reader() } else { backing.ring.open_reader() } diff --git a/kernel/src/process.rs b/kernel/src/process.rs index 7a6811c359e..88c157fe60d 100644 --- a/kernel/src/process.rs +++ b/kernel/src/process.rs @@ -35,7 +35,7 @@ use toyos_proclife::{join, reap, spawn as proclife_spawn, teardown as proclife, /// One `EndowEntry` on the wire; `loader::start` and [`Endowments::encode`] both index by it. pub const ENDOW_ENTRY_LEN: usize = core::mem::size_of::(); -pub use crate::loader::{build_child_handles, spawn, spawn_init, INIT_PATH}; +pub use crate::loader::{build_child_handles, spawn, spawn_supervisor, SUPERVISOR_PATH}; /// Page tables shared between a process and all its threads. pub type PageTables = Arc>; @@ -848,7 +848,7 @@ pub fn with_process_data(f: impl FnOnce(&mut ProcessData) -> R) -> R { /// Whom a new process is placed under. #[derive(Clone, Copy)] pub enum Parent { - /// No process: init, which the kernel starts. + /// No process: the supervisor, which the kernel starts. Root, /// The spawner, or the process whose `self` its place named. Under(Pid), @@ -858,7 +858,7 @@ pub enum Parent { pub struct Admission(Option); impl Admission { - /// The question at the top of a spawn, before anything is built: `Gone` for a parent being torn down, and `ResourceExhausted`, which the log names, for a child more than `MAX_DEPTH` below init or no pid left to issue. + /// The question at the top of a spawn, before anything is built: `Gone` for a parent being torn down, and `ResourceExhausted`, which the log names, for a child more than `MAX_DEPTH` below the supervisor or no pid left to issue. pub fn ask(parent: Parent) -> Result { let place = match parent { Parent::Root => None, @@ -872,8 +872,8 @@ impl Admission { tree::Admit::Yes(admitted) => Ok(Self(Some(admitted))), tree::Admit::Gone => Err(SyscallError::Gone), tree::Admit::TooDeep { depth } => { - log!("spawn: refused under pid {} at depth {depth}, more than {} below init", - place.expect("spawn: init is admitted at depth 0"), toyos_proclife::MAX_DEPTH); + log!("spawn: refused under pid {} at depth {depth}, more than {} below the supervisor", + place.expect("spawn: the supervisor is admitted at depth 0"), toyos_proclife::MAX_DEPTH); Err(SyscallError::ResourceExhausted) } tree::Admit::NoPid => { diff --git a/kernel/src/rootfs.rs b/kernel/src/rootfs.rs index eb55f8a27ee..926cbd5e04e 100644 --- a/kernel/src/rootfs.rs +++ b/kernel/src/rootfs.rs @@ -25,9 +25,9 @@ use crate::sync::Lock; /// The unit ROOT's filesystem is written in, which is the page. const BLOCK: usize = crate::mm::PAGE_SIZE as usize; -/// The record init's spawn is reported on, followed by how many storage +/// The record the supervisor's spawn is reported on, followed by how many storage /// commands the boot had issued by then: zero is the claim. -pub const INIT_WITHOUT_A_DISK: &str = "boot: init spawned with ROOT from memory; storage commands before it:"; +pub const SUPERVISOR_WITHOUT_A_DISK: &str = "boot: the supervisor spawned with ROOT from memory; storage commands before it:"; /// The record a ROOT mounted off the loader's image is reported on. pub const MOUNTED_FROM_MEMORY: &str = "root: mounted read-only from memory at"; @@ -178,7 +178,7 @@ pub fn hold_source() { .map_err(|()| "it is no span a view can hold") } // Every disk this kernel drives answered and lacks it: a disk a process - // drives, NVMe's under blockd, is never asked. + // drives, NVMe's under diskserver, is never asked. Ok(None) if sought.silent.is_empty() => Err("it is on no disk this kernel drives"), Ok(None) => Err("it is on no disk that answered"), Err(Unnamed::Ambiguous) => Err("it is carried twice"), diff --git a/kernel/src/sched/driver.rs b/kernel/src/sched/driver.rs index 800611f60c5..97b54c993a3 100644 --- a/kernel/src/sched/driver.rs +++ b/kernel/src/sched/driver.rs @@ -386,7 +386,7 @@ fn idle_ctx() -> KernelCtx { } /// Where a spawn goes: the rule is [`CpuHandles::place`]'s; this supplies the rotating start, load-bearing at -/// boot since every init program is spawned before any CPU has published a load. +/// boot since every program the supervisor starts is spawned before any CPU has published a load. fn placement(now: Nanos) -> CpuId { static ROTATE: AtomicU64 = AtomicU64::new(0); let count = crate::smp::cpu_count() as u64; diff --git a/kernel/src/syscall/device.rs b/kernel/src/syscall/device.rs index 85c5fd3202a..9984855ba29 100644 --- a/kernel/src/syscall/device.rs +++ b/kernel/src/syscall/device.rs @@ -139,7 +139,7 @@ pub(super) fn sys_device_claim(syscap: RawHandle, class: u64, selector: [u64; 2] if let Err(e) = demand_syscap(syscap, Rights::DEVICE) { return e.refuse(); } - // Each refusal keeps its own word: init logs what it could not mint, and + // Each refusal keeps its own word: the supervisor logs what it could not mint, and // "this machine has none" is a configuration while the rest are faults. let claim = match device::try_claim(class, selector) { Ok(c) => c, diff --git a/kernel/src/syscall/machine.rs b/kernel/src/syscall/machine.rs index e79004b4334..4c2009f7492 100644 --- a/kernel/src/syscall/machine.rs +++ b/kernel/src/syscall/machine.rs @@ -2,7 +2,7 @@ //! //! [`sys_log_read`], the roster half of [`sys_sysinfo`], and both of //! [`sys_shutdown`] and [`sys_reboot`] each require a `SysCap` bit from -//! `/system/bin/init`'s `system.toml`; `SYS_SYSINFO`'s header is ambient, and +//! `/system/bin/supervisor`'s `system.toml`; `SYS_SYSINFO`'s header is ambient, and //! [`sys_sched_info`] demands nothing. use alloc::vec::Vec; @@ -67,7 +67,7 @@ fn quiesce(last: &str) -> Result<(), SyscallError> { // First: what follows outlasts a feed cadence, and no pass runs to feed again. crate::arch::watchdog::disarm(); // Every userland thread stops here, the log's writer with the rest: - // `/system/bin/init` had it flush before it asked for this stop. + // `/system/bin/supervisor` had it flush before it asked for this stop. let stopped = crate::quiesce::stop(); crate::log::console::drain_for_the_stop(); // The final census: no process runs after this to report another. diff --git a/rust b/rust index 95960d6c214..a0d44493347 160000 --- a/rust +++ b/rust @@ -1 +1 @@ -Subproject commit 95960d6c214338e9375b1c7c6c0d4e5ece4c4ba3 +Subproject commit a0d44493347e5be082ed4b7507b53537bab2c884 diff --git a/src/CLAUDE.md b/src/CLAUDE.md index e3f19a0ae2f..8305ccad4ef 100644 --- a/src/CLAUDE.md +++ b/src/CLAUDE.md @@ -5,7 +5,7 @@ Loads when you read a file under `src/` — the root cargo project, package name ## Entry points - **`.github/qemu-version` is the QEMU every guest is measured with, declared once**; every guest job's first step (`src/ci.rs`'s `instrument`) reds on a disagreement. -- `system.toml` defines which programs to build and the init sequence. +- `system.toml` defines which programs to build and what the supervisor starts at boot. ## The host's locks diff --git a/src/bootlog.rs b/src/bootlog.rs index 0d67da44022..34fbb3038c2 100644 --- a/src/bootlog.rs +++ b/src/bootlog.rs @@ -16,7 +16,7 @@ use std::fmt; /// running to write it there. pub const REBOOTING: &str = "Rebooting."; -/// What `/system/bin/init` says as it asks `logd` to make the log whole, before +/// What `/system/bin/supervisor` says as it asks `logkeeper` to make the log whole, before /// it stops the machine: the last line a passing boot's log is owed, because /// nothing after it waits for the file. pub const STOPPING: &str = toyos_logstream::STOPPING; @@ -31,7 +31,7 @@ pub const JOB_DEADLINE_SAID: &str = /// What the kernel's own boot deadline writes into the black box as it ends the /// machine, in `kernel/src/deadline.rs`. The loader prints it back under /// [`PREVIOUS_PANIC`] on the pass after the reset, and that is the only channel -/// it has: a wedged boot's `logd` wrote nothing. +/// it has: a wedged boot's `logkeeper` wrote nothing. pub const DEADLINE_EXPIRED: &str = "the boot deadline expired"; /// What the kernel logs as it arms that deadline, in `kernel/src/deadline.rs`: @@ -81,7 +81,7 @@ pub const LOCKED_UP: &str = "a cpu locked up with interrupts off"; /// `kernel/src/log/mod.rs`'s `seal_tail`: the head of the boot's newest /// records. The next loader pass prints it back under [`PREVIOUS_PANIC`]. /// -/// **The one reader a boot's own tail has.** The stop stops `logd` with every +/// **The one reader a boot's own tail has.** The stop stops `logkeeper` with every /// other thread, so what the kernel says from there on — the stop's record, /// its census, [`REBOOTING`] — is on the console and here, and on a machine /// with no serial port a console is nothing. @@ -158,7 +158,7 @@ pub const SEPARATOR: &str = "--- the pass after the reset, reading what the boot /// **One channel carries it after the console**: the black-box page, where a /// boot that handed the machine back seals it among its [`LOG_TAIL`] records /// and a boot a bound ended seals it with its record. The stop writes it after -/// `logd` has stopped, so no file does. +/// `logkeeper` has stopped, so no file does. pub const PANEL_CENSUS: &str = "panel: paints="; /// What one boot's panel census says: how often the panel painted, how many @@ -176,7 +176,7 @@ pub struct Panel { /// /// **This boot's census whole, or nothing.** A `max_us=` whose digits a cut /// took the end of parses as a cheaper panel than the boot had, and each -/// channel says a line ended itself in its own way: `logd`'s file terminates +/// channel says a line ended itself in its own way: `logkeeper`'s file terminates /// one, and the black-box page is a fixed size whose one cut line the loader /// closes with [`CUT_BY_THE_PAGE`]. An older census standing in for a cut one /// would be a second boot's number under this boot's name, so the cut line is @@ -214,7 +214,7 @@ pub fn message(line: &str) -> Option<&str> { } /// Whether a line of the log is a program's (`toyos_logstream::ProgramLine`): -/// `logd` writes that head and no kernel record opens with it. +/// `logkeeper` writes that head and no kernel record opens with it. pub fn is_program_line(line: &str) -> bool { toyos_logstream::is_program_line(line) } @@ -224,7 +224,7 @@ pub fn kernel_records(log: &str) -> String { log.split_inclusive('\n').filter(|line| !is_program_line(line)).collect() } -/// One program's lines, by the name init started it under, as `logd` read them +/// One program's lines, by the name the supervisor started it under, as `logkeeper` read them /// out of its log ring: each line's text, newline-terminated. pub fn lines_of(log: &str, name: &str) -> String { log.lines() @@ -252,33 +252,33 @@ pub fn recorded_name(binary: &str) -> String { base[..base.len().min(NAME_LEN - 1)].to_string() } -/// Whether `name` on the log volume is one of `logd`'s files, which is -/// `logd`'s own allow-list and not a suffix: the loader's file ends in `.log` +/// Whether `name` on the log volume is one of `logkeeper`'s files, which is +/// `logkeeper`'s own allow-list and not a suffix: the loader's file ends in `.log` /// too, and a `toybox` run can leave anything there. -pub fn is_logd_file(name: &str) -> bool { +pub fn is_logkeeper_file(name: &str) -> bool { toyos_wallclock::classify(name).is_some() } /// The names on a mounted log volume, split into the loader's file and -/// `logd`'s in the order theirs sort. +/// `logkeeper`'s in the order theirs sort. /// /// The loader's is matched without case, because a FAT driver that does not -/// read the lowercase flags in a directory entry yields `LOADER.LOG`; `logd`'s +/// read the lowercase flags in a directory entry yields `LOADER.LOG`; `logkeeper`'s /// are matched as its own writer spells them, which no such driver preserves -/// either — a volume read through one has no `logd` file this can name, and +/// either — a volume read through one has no `logkeeper` file this can name, and /// says so by finding none. pub fn split_listing(listing: &str) -> (Option<&str>, Vec<&str>) { let mut loader = None; - let mut logd = Vec::new(); + let mut logkeeper = Vec::new(); for name in listing.lines().map(str::trim).filter(|name| !name.is_empty()) { if name.eq_ignore_ascii_case(LOADER_LOG) { loader = Some(name); - } else if is_logd_file(name) { - logd.push(name); + } else if is_logkeeper_file(name) { + logkeeper.push(name); } } - logd.sort_unstable(); - (loader, logd) + logkeeper.sort_unstable(); + (loader, logkeeper) } /// The kernel's boot-phase record for the end of boot, in @@ -289,7 +289,7 @@ pub const COMPLETE: &str = "Boot: complete ("; #[derive(Debug, Clone, PartialEq, Eq)] pub enum Unfit { NoBootRecord, - /// The log carries no word from init that the machine stops: the last + /// The log carries no word from the supervisor that the machine stops: the last /// line it carries instead. Unfinished(String), /// The loader pass after the reset read no `DONE`, or read one with no @@ -306,8 +306,8 @@ impl fmt::Display for Unfit { Self::NoBootRecord => write!(f, "the log carries no `{COMPLETE}Nms)` record"), Self::Unfinished(saw) => write!( f, - "the log's last line is {saw:?} and init never said {STOPPING:?}: either the \ - boot never asked to hand the machine back to the firmware, or logd never made \ + "the log's last line is {saw:?} and the supervisor never said {STOPPING:?}: either the \ + boot never asked to hand the machine back to the firmware, or logkeeper never made \ the log whole before it did" ), Self::NotHandedBack => write!( @@ -352,11 +352,11 @@ pub fn after_the_reset(loader: &str) -> Option<&str> { loader.find(SEPARATOR).map(|at| &loader[at..]) } -/// Init's line saying the machine stops, the last one `log` carries. +/// The supervisor's line saying the machine stops, the last one `log` carries. pub fn stopping_line(log: &str) -> Option<&str> { log.lines().rfind(|line| { toyos_logstream::program_line(line) - .is_some_and(|said| said.tag == "init" && said.text.starts_with(STOPPING)) + .is_some_and(|said| said.tag == "supervisor" && said.text.starts_with(STOPPING)) }) } @@ -364,7 +364,7 @@ pub fn stopping_line(log: &str) -> Option<&str> { /// /// **Found from the CPU it precedes rather than by position**: the field before /// it is the writer's tag, and the two writers disagree about it on purpose — -/// `logd` puts a wall clock there and the panel puts nothing. +/// `logkeeper` puts a wall clock there and the panel puts nothing. pub fn record_millis(line: &str) -> Option { toyos_logstream::record_ms(line) } @@ -403,8 +403,8 @@ pub fn boot_millis(log: &str) -> Option { } /// A boot's duration if its log is a passing boot's, which takes both lines: -/// the kernel's boot record, and init's word that the machine stops — said -/// before `logd` made the log whole, so a log that carries it is whole to it. +/// the kernel's boot record, and the supervisor's word that the machine stops — said +/// before `logkeeper` made the log whole, so a log that carries it is whole to it. /// That the reset then came is the console's to say, or the next loader /// pass's ([`HANDED_BACK`], and [`REBOOTING`] under [`LOG_TAIL`]). pub fn verdict(log: &str) -> Result { @@ -421,26 +421,26 @@ mod tests { use super::*; /// The half-told boot: the kernel got all the way up and the log stops - /// there, so the machine either never asked for the reset or `logd` never + /// there, so the machine either never asked for the reset or `logkeeper` never /// made the log whole before it. #[test] - fn a_boot_record_without_inits_stop_is_not_a_pass() { + fn a_boot_record_without_the_supervisors_stop_is_not_a_pass() { let booted = "[kernel 1.151 cpu0] Boot: complete (1151ms)\n"; - let stopping = format!("{{1.203 init}} {STOPPING} (Reboot)\n"); + let stopping = format!("{{1.203 supervisor}} {STOPPING} (Reboot)\n"); let ended = format!("{booted}{stopping}"); assert_eq!(verdict(&ended), Ok(1151)); - // What `logd` wrote between the flush and the stop is no refusal. + // What `logkeeper` wrote between the flush and the stop is no refusal. assert_eq!(verdict(&format!("{ended}[kernel 1.210 cpu0] exit: reboot pid=6\n")), Ok(1151)); assert_eq!( verdict(booted), Err(Unfit::Unfinished("[kernel 1.151 cpu0] Boot: complete (1151ms)".to_string())) ); - // The words, from anyone but init, and from init as anything but its - // line, are not init's stop. + // The words, from anyone but the supervisor, and from the supervisor as anything but its + // line, are not the supervisor's stop. let forged = format!("{booted}{{1.203 test-runner}} {STOPPING}\n"); assert!(matches!(verdict(&forged), Err(Unfit::Unfinished(_)))); - let quoted = format!("{booted}{{1.203 init}} init: said {STOPPING}\n"); + let quoted = format!("{booted}{{1.203 supervisor}} supervisor: said {STOPPING}\n"); assert!(matches!(verdict("ed), Err(Unfit::Unfinished(_)))); assert_eq!(verdict(&stopping), Err(Unfit::NoBootRecord)); assert_eq!(verdict(""), Err(Unfit::NoBootRecord)); @@ -509,7 +509,7 @@ mod tests { } #[test] - fn the_loaders_file_is_told_from_logds_however_a_driver_spelled_it() { + fn the_loaders_file_is_told_from_logkeepers_however_a_driver_spelled_it() { let listing = "2026-09-06-084003.log\nloader.log\nunknown-00.log\nnotes.txt\n"; assert_eq!( split_listing(listing), @@ -517,7 +517,7 @@ mod tests { ); // A FAT driver that drops the lowercase flags yields 8.3 in upper case. assert_eq!(split_listing("LOADER.LOG\n").0, Some("LOADER.LOG")); - // And it is never one of logd's, under either spelling. + // And it is never one of logkeeper's, under either spelling. assert!(split_listing("LOADER.LOG\nloader.log\n").1.is_empty()); // Blank rows and stray whitespace are a listing's, not a name's. assert_eq!(split_listing("\n loader.log \n\n").0, Some("loader.log")); @@ -566,12 +566,12 @@ mod tests { let log = "[2026-09-08 16:08:23 2.100 cpu0] exit: test_rs_job pid=4 code=3 cpu=1ms\n\ [2026-09-08 16:08:23 2.150 cpu0] PANIC: a report\n its second line\n\ {2026-09-08 16:08:23 2.200 test-runner} [2026-09-08 16:08:23 2.200 cpu0] exit: test_rs_job pid=4 code=0 cpu=0ms\n\ - {2026-09-08 16:08:23 2.300 test-runner} {x 2.3 netd} netd: MAC 00:00:00:00:00:00\n\ - {2026-09-08 16:08:23 2.400 netd} netd: MAC 52:54:00:12:34:56\n"; + {2026-09-08 16:08:23 2.300 test-runner} {x 2.3 netstack} netstack: MAC 00:00:00:00:00:00\n\ + {2026-09-08 16:08:23 2.400 netstack} netstack: MAC 52:54:00:12:34:56\n"; let kernel = kernel_records(log); assert!(!kernel.contains("code=0"), "{kernel}"); assert!(kernel.contains("code=3") && kernel.contains(" its second line\n"), "{kernel}"); - assert_eq!(lines_of(log, "netd"), "netd: MAC 52:54:00:12:34:56\n"); + assert_eq!(lines_of(log, "netstack"), "netstack: MAC 52:54:00:12:34:56\n"); assert_eq!(lines_of(log, "test-runner").lines().count(), 2); assert!(is_program_line(log.lines().nth(3).expect("five lines"))); } @@ -598,7 +598,7 @@ mod tests { mod record_time_tests { use super::*; - /// Both writers' shapes: `logd`'s file carries a wall-clock tag before the + /// Both writers' shapes: `logkeeper`'s file carries a wall-clock tag before the /// elapsed field and the panel carries none, and the same reader answers /// for both. #[test] @@ -618,15 +618,15 @@ mod record_time_tests { assert_eq!(record_millis(""), None); } - /// The two channels the census crosses, read by one reader: `logd`'s file, + /// The two channels the census crosses, read by one reader: `logkeeper`'s file, /// and the black-box page the loader prints back with its own margin and /// with the kernel's dashes flattened to ASCII. #[test] fn the_panel_census_is_read_off_either_channel() { - let logd = "[2026-09-08 06:50:53 2.5 cpu0] panel: paints=3 px=6220800 us=1500000 \ + let logkeeper = "[2026-09-08 06:50:53 2.5 cpu0] panel: paints=3 px=6220800 us=1500000 \ max_us=520000\n"; assert_eq!( - panel_census(logd), + panel_census(logkeeper), Some(Panel { paints: 3, pixels: 6_220_800, micros: 1_500_000, max_micros: 520_000 }) ); @@ -659,7 +659,7 @@ mod record_time_tests { let mid_number = format!("paints=10 px=8886656 us=18693 max_us=38{CUT_BY_THE_PAGE}"); assert_eq!(panel_census(&page(&mid_number, "")), None); - // `logd`'s file ends a record with the newline, so its own cut is a + // `logkeeper`'s file ends a record with the newline, so its own cut is a // last line that never got one. assert_eq!(panel_census("panel: paints=3 px=6220800 us=1500000 max_us=52"), None); // A field the cut took whole, and a log with no census at all. diff --git a/src/build.rs b/src/build.rs index ee955a2ada5..9a2c6d839b6 100644 --- a/src/build.rs +++ b/src/build.rs @@ -111,7 +111,7 @@ struct SystemConfig { hosted_rustc: bool, #[serde(default)] assets: Vec, - /// What `/system/bin/init` starts at boot. Program *keys*, never paths — a path + /// What `/system/bin/supervisor` starts at boot. Program *keys*, never paths — a path /// here is a second spelling of a `[programs]` key and is what let a boot /// list smuggle an argument through. Arguments live on the program entry's /// `args` instead. @@ -144,30 +144,30 @@ struct ProgramConfig { no_default_features: bool, /// Argv this program is started with, after argv[0]. args: Vec, - /// Names init creates **one machine-wide port** for and endows this program + /// Names the supervisor creates **one machine-wide port** for and endows this program /// the *acceptor* of. serves: Vec, /// Names this program creates a port for **itself**, once per instance, and - /// hands the connector down to its own children. init creates nothing and + /// hands the connector down to its own children. The supervisor creates nothing and /// holds nothing for these — `surface` is the whole of this kind. provides: Vec, /// Names in this program's namespace, each a *connector*. receives: Vec, - /// Device classes init mints a claim for and endows. + /// Device classes the supervisor mints a claim for and endows. devices: Vec, - /// Rights on the `SysCap` duplicate init endows this program, by the names + /// Rights on the `SysCap` duplicate the supervisor endows this program, by the names /// `toyos_manifest::syscap_rights` takes. A handful of rows in the whole /// tree declare one. syscap: Vec, /// The idle slot, granted as partition claims (`toyos_manifest::Program::slots`). slots: bool, - /// A system service: init starts it with `HOME` at its own `/state/` + /// A system service: the supervisor starts it with `HOME` at its own `/state/` /// and makes that directory, where every other row gets the session's. service: bool, /// The file-server roles this binary serves, one process each /// (`toyos_manifest::Program::roles`). roles: Vec, - /// init starts it again when it ends (`toyos_manifest::Program::restart`). + /// The supervisor starts it again when it ends (`toyos_manifest::Program::restart`). restart: bool, } @@ -382,8 +382,8 @@ fn config_crates(root: &Path, config: &SystemConfig) -> Vec { }); } crates.push(ConfigCrate { - name: INIT_PROGRAM.to_string(), - dir: ProgramConfig::default().crate_dir(root, INIT_PROGRAM), + name: SUPERVISOR_PROGRAM.to_string(), + dir: ProgramConfig::default().crate_dir(root, SUPERVISOR_PROGRAM), built: Built::Member, features: Features::Default, }); @@ -487,14 +487,6 @@ fn cargo_build( // So: hold [`buildlock::artifact`] across each build→stage pair, and copy the // artifact to a name carrying what it is actually keyed by. Readers use the // staged name, which no other config can overwrite. -// -// The bootloader used to be here for the same reason and no longer is: its init -// list was compiled into it, so the `.efi` was a function of the boot config, -// and an image once carried metalcase's root image beside another config's -// bootloader whose 28-byte init string was `"/system/bin/soundd;/system/bin/test-runner"` — -// the compositor was never spawned and the test failed as though the daemon -// under test were broken. The bootloader carries no config now, so it is -// memoized once per profile and that hazard is not expressible. /// The staged-artifact key of a kernel built with `features`. /// @@ -635,15 +627,15 @@ fn assert_overflow_checked(what: &str, image: &[u8]) { /// The one program the kernel starts, in **every** image whatever `[programs]` /// says. It reads the manifest below and starts what that names, so a ROOT image /// without it is a machine with a kernel and no userland at all. -const INIT_PROGRAM: &str = "init"; +const SUPERVISOR_PROGRAM: &str = "supervisor"; -/// Names `/system/bin/init` serves itself. +/// Names `/system/bin/supervisor` serves itself. /// -/// init is in every image and is no `[programs]` key, so these have no -/// declaration to come from. They travel in the manifest so init creates +/// The supervisor is in every image and is no `[programs]` key, so these have no +/// declaration to come from. They travel in the manifest so the supervisor creates /// exactly the ports the build-time gate counted as provided — one producer, -/// rather than a constant here and a string in init. -const INIT_SERVED: &[&str] = &["launcher", toyos_swap::PORT, "power"]; +/// rather than a constant here and a string in the supervisor. +const SUPERVISOR_SERVED: &[&str] = &["launcher", toyos_swap::PORT, "power"]; /// Who may hold the two authorities that change what the machine runs: /// the swap port, [`toyos_swap::HOLDER`] and nothing else — no other @@ -672,10 +664,10 @@ fn held_by_their_holders_alone(config: &SystemConfig) -> Result<(), String> { Ok(()) } -/// The resolved config as the records `/system/bin/init` reads. +/// The resolved config as the records `/system/bin/supervisor` reads. /// /// The format, the renderer and the parser are `toyos-manifest/`, whose -/// round-trip test is what makes "what the build writes is what init reads" a +/// round-trip test is what makes "what the build writes is what the supervisor reads" a /// fact rather than two hand-matched implementations. fn render_manifest(config: &SystemConfig) -> Vec { if let Err(why) = held_by_their_holders_alone(config) { @@ -704,7 +696,7 @@ fn render_manifest(config: &SystemConfig) -> Vec { } }) .collect(), - init_serves: INIT_SERVED.iter().map(|s| (*s).to_string()).collect(), + supervisor_serves: SUPERVISOR_SERVED.iter().map(|s| (*s).to_string()).collect(), apps: config.apps.receives.clone(), start: config.boot.start.clone(), }; @@ -796,7 +788,7 @@ fn not_built_for(arch: Arch, program: &str) -> Option<&'static str> { NOT_YET_BUILT.iter().find(|(a, name, _)| *a == arch && *name == program).map(|(_, _, why)| *why) } -/// Build `config`'s programs and init for `arch`, and add each to `root_files`. +/// Build `config`'s programs and the supervisor for `arch`, and add each to `root_files`. fn build_programs( root: &Path, config: &SystemConfig, @@ -882,7 +874,7 @@ fn symlink_target_name(to: &str) -> &str { } /// The converse of the crate assertion above: a `bin/` entry no name reaches. -/// A name buys authority — `/system/bin/init` builds a `[programs]` row's namespace and +/// A name buys authority — `/system/bin/supervisor` builds a `[programs]` row's namespace and /// device claims — and a harness binary has none, holding only what its spawner /// moved in, so it is legal exactly when the config starts something that could /// spawn it. **An inventory over the `bin/` namespace, not a reachability @@ -894,7 +886,7 @@ fn unnamed_program( ) -> Result<(), String> { for name in names { let Some(program) = name.strip_prefix("bin/") else { continue }; - if program == INIT_PROGRAM || programs.contains(program) { + if program == SUPERVISOR_PROGRAM || programs.contains(program) { continue; } if HARNESS_PREFIXES.iter().any(|p| name.starts_with(p)) { @@ -909,7 +901,7 @@ fn unnamed_program( continue; } return Err(format!( - "the image carries {name} and no `[programs]` row names it, so `/system/bin/init` can build \ + "the image carries {name} and no `[programs]` row names it, so `/system/bin/supervisor` can build \ it no namespace and no device claim; add a row or take the file out" )); } @@ -1826,7 +1818,7 @@ pub fn designate_for_format(path: &Path, len: u64) { /// run asks cargo again. /// /// Per part rather than per image, because a part is what a key can be true of: -/// the kernel is its feature set, the bootloader is its init list, the ROOT image is +/// the kernel is its feature set, the ROOT image is /// its config and the caller's extra files. That is the same split /// [`stage_artifact`] already writes into the artifact names, and it is what /// makes this affordable — a full run boots a handful of kernels, and builds @@ -2054,7 +2046,7 @@ pub fn copy_guest_program(root: &Path, arch: Arch, name: &str, to: &Path) -> Res } /// The harness's SSH client — the only thing in this tree that speaks the -/// protocol from the other side of `userland/sshd`. +/// protocol from the other side of `userland/sshserver`. pub fn ssh_client_host(root: &Path) -> PathBuf { host_judge(root, SSH_CLIENT) } @@ -2263,15 +2255,15 @@ fn collect_hosted_rustc(root: &Path, toolchain: &Path, root_files: &mut Vec<(Str mod tests { use super::*; - /// `console` is reached by `console/system.toml` alone and `init` by no - /// `[programs]` row, so a reader that drops a mode or init loses one. + /// `console` is reached by `console/system.toml` alone and the supervisor by no + /// `[programs]` row, so a reader that drops a mode or the supervisor loses one. #[test] - fn every_modes_crates_and_init_ship() { + fn every_modes_crates_and_the_supervisor_ship() { let root = Path::new(env!("CARGO_MANIFEST_DIR")); let shipped = shipped(root).expect("the modes' configs"); for (dir, features) in [ ("userland/console", Features::Default), - ("userland/init", Features::Default), + ("userland/supervisor", Features::Default), ("kernel", Features::AnyDeclared), ("bootloader", Features::Default), ] { @@ -2333,7 +2325,7 @@ mod tests { let crates = [&kernel, &loader, &userland]; let kernels = Arch::ALL.map(|arch| file(kernel.join(format!("target/{}/{PROFILE}/kernel", arch.kernel())))); let loaders = Arch::ALL.map(|arch| file(loader.join(format!("target/{}/{PROFILE}/loader.efi", arch.loader())))); - let programs = Arch::ALL.map(|arch| file(userland.join(format!("target/{}/{PROFILE}/init", arch.userland())))); + let programs = Arch::ALL.map(|arch| file(userland.join(format!("target/{}/{PROFILE}/supervisor", arch.userland())))); let hosts = crates.map(|dir| file(dir.join(format!("target/{PROFILE}/deps/libproc-1.dylib")))); let before = Identity::of_parts("compiler", "freestanding", "toyos"); @@ -2861,22 +2853,22 @@ mod tests { assert_eq!(not_built_for(Arch::X86_64, "calc"), None, "x86-64 builds every program"); } - /// No image this repository ships starts sshd. + /// No image this repository ships starts sshserver. /// /// It listens on every interface and authenticates against a file that is /// absent on a fresh install, so on a default boot it would be a port that /// accepts connections and refuses all of them. Whoever wants it runs - /// `/system/bin/sshd` themselves. It stays in `[programs]` — the gate is on what - /// init starts, not on the binary being present. + /// `/system/bin/sshserver` themselves. It stays in `[programs]` — the gate is on what + /// the supervisor starts, not on the binary being present. #[test] - fn no_shipped_boot_config_starts_sshd() { + fn no_shipped_boot_config_starts_sshserver() { let root = Path::new(env!("CARGO_MANIFEST_DIR")); for boot in [Boot::shipped(root), Boot::diag(root), Boot::console(root)] { let config = boot.config.clone(); let start = parse_config(&config).boot.start; assert!( - !start.iter().any(|p| p == "sshd"), - "{} starts sshd: {start:?}", + !start.iter().any(|p| p == "sshserver"), + "{} starts sshserver: {start:?}", config.display(), ); } @@ -2953,11 +2945,11 @@ mod tests { assert!(refusal.contains("not in this repository"), "{refusal}"); } - /// **Every config with a `[boot] start` runs `/system/bin/logd`, `logd` always holds + /// **Every config with a `[boot] start` runs `/system/bin/logkeeper`, `logkeeper` always holds /// `logread`, and nothing outside the cursor readers ever does.** /// - /// The kernel writes no file — `/system/bin/logd` owns `/log` and reads records off - /// a cursor — so a boot config that does not start `logd` is an image whose + /// The kernel writes no file — `/system/bin/logkeeper` owns `/log` and reads records off + /// a cursor — so a boot config that does not start `logkeeper` is an image whose /// log partition stays empty for the whole of that boot — and on /// the machine this subsystem exists for, a T14 with no serial port, that is /// the boot with no record of itself anywhere. A config added later fails @@ -2968,8 +2960,8 @@ mod tests { /// `Rights::LOG | Rights::WAIT` on a `SysCap` duplicate, which is authority /// over every record every CPU wrote, and a right with no caller is a /// capability handed out for a plan. Two programs read a cursor — - /// `/system/bin/logd`, which writes the file, and `test-runner`, which runs the - /// conservation gates inside itself. `logd` always does, since that is its + /// `/system/bin/logkeeper`, which writes the file, and `test-runner`, which runs the + /// conservation gates inside itself. `logkeeper` always does, since that is its /// whole job; `test-runner` does where an estate runs such a gate and not /// where it runs none. `/system/bin/console` is the near miss: it *could* show this boot's /// records live off a cursor, and holds the right only once something reads one. @@ -2978,25 +2970,25 @@ mod tests { /// over the TOML would pass on a row that is commented out and on a key /// `serde` never saw. #[test] - fn every_boot_config_runs_logd() { - const READERS: &[&str] = &["logd", "test-runner"]; + fn every_boot_config_runs_logkeeper() { + const READERS: &[&str] = &["logkeeper", "test-runner"]; let root = Path::new(env!("CARGO_MANIFEST_DIR")); for config in ALL_CONFIGS { let parsed = parse_config(&root.join(config)); assert!( - parsed.boot.start.iter().any(|p| p == "logd"), - "{config} declares `[boot] start = {:?}` and no `logd` in it, so this image's \ + parsed.boot.start.iter().any(|p| p == "logkeeper"), + "{config} declares `[boot] start = {:?}` and no `logkeeper` in it, so this image's \ /log is empty for the whole boot", parsed.boot.start, ); assert!( - parsed.programs.contains_key("logd"), - "{config} starts `logd` and has no `[programs.logd]` row to say what it holds", + parsed.programs.contains_key("logkeeper"), + "{config} starts `logkeeper` and has no `[programs.logkeeper]` row to say what it holds", ); for (name, program) in &parsed.programs { let holds = program.syscap.iter().any(|s| s == "logread"); - if name == "logd" { - assert!(holds, "{config}: `logd` writes the file and must read the cursor"); + if name == "logkeeper" { + assert!(holds, "{config}: `logkeeper` writes the file and must read the cursor"); continue; } assert!( @@ -3008,21 +3000,21 @@ mod tests { } } - /// **An image a user boots serves no log on the network.** `logd` answers + /// **An image a user boots serves no log on the network.** `logkeeper` answers /// `toyos_logstream::PORT` to whoever connects, with nothing to authenticate - /// them, once it holds a `netd` connector: the test configs that read the + /// them, once it holds a `netstack` connector: the test configs that read the /// stream give it one, and these do not. #[test] fn no_shipped_image_serves_the_log_on_the_network() { let root = Path::new(env!("CARGO_MANIFEST_DIR")); for config in ALL_CONFIGS.iter().filter(|config| !config.starts_with("tests/")) { let parsed = parse_config(&root.join(config)); - let logd = parsed.programs.get("logd").expect("every config runs logd"); + let logkeeper = parsed.programs.get("logkeeper").expect("every config runs logkeeper"); assert!( - logd.receives.is_empty(), - "{config}: `logd` receives {:?}, and a `netd` connector is what serves this \ + logkeeper.receives.is_empty(), + "{config}: `logkeeper` receives {:?}, and a `netstack` connector is what serves this \ machine's log to anyone on its network", - logd.receives, + logkeeper.receives, ); } } @@ -3039,7 +3031,7 @@ mod tests { } } - /// One prefix and no other, so a doc naming `/etc/logd` or `/apps/logd` is a + /// One prefix and no other, so a doc naming `/etc/logkeeper` or `/apps/logkeeper` is a /// token the filter below drops and an assertion that reds. const LOG_DOC_BIN: &str = "/system/bin/"; @@ -3123,11 +3115,11 @@ mod tests { } /// Every name a program `receives` must be served or provided by some - /// program in the *same* config, or served by init. The build-time form of + /// program in the *same* config, or served by the supervisor. The build-time form of /// "a client cannot name a service the system does not have", and the gate /// with the sharpest teeth: no guest, no mutated tree. fn receives_have_providers(cfg: &SystemConfig) -> Result<(), String> { - let mut providers: Vec<&str> = INIT_SERVED.to_vec(); + let mut providers: Vec<&str> = SUPERVISOR_SERVED.to_vec(); for prog in cfg.programs.values() { providers.extend(prog.serves.iter().map(String::as_str)); providers.extend(prog.provides.iter().map(String::as_str)); @@ -3150,7 +3142,7 @@ mod tests { receives_have_providers(&load(cfg)).unwrap_or_else(|e| panic!("{cfg}: {e}")); } let bad: SystemConfig = - toml::from_str("init = []\n[programs.client]\nreceives = [\"ghost\"]\n").unwrap(); + toml::from_str("[programs.client]\nreceives = [\"ghost\"]\n").unwrap(); assert!(receives_have_providers(&bad).is_err()); } @@ -3168,9 +3160,9 @@ mod tests { let shell: SystemConfig = toml::from_str("[programs.shell]\nreceives = [\"swap\"]\n").unwrap(); assert!(held_by_their_holders_alone(&shell).is_err()); - let sshd: SystemConfig = - toml::from_str("[programs.sshd]\nreceives = [\"netd\", \"swap\"]\n").unwrap(); - assert!(held_by_their_holders_alone(&sshd).is_err()); + let sshserver: SystemConfig = + toml::from_str("[programs.sshserver]\nreceives = [\"netstack\", \"swap\"]\n").unwrap(); + assert!(held_by_their_holders_alone(&sshserver).is_err()); let apps: SystemConfig = toml::from_str("[apps]\nreceives = [\"swap\"]\n").unwrap(); assert!(held_by_their_holders_alone(&apps).is_err()); let slots: SystemConfig = toml::from_str("[programs.shell]\nslots = true\n").unwrap(); @@ -3179,9 +3171,9 @@ mod tests { /// `[apps] receives` is narrower than a program's: a `provides` name is one /// port per instance and nobody makes one for a package, so naming one here - /// is a namespace init cannot build. + /// is a namespace the supervisor cannot build. fn apps_receive_a_served_name(cfg: &SystemConfig) -> Result<(), String> { - let mut served: Vec<&str> = INIT_SERVED.to_vec(); + let mut served: Vec<&str> = SUPERVISOR_SERVED.to_vec(); for prog in cfg.programs.values() { served.extend(prog.serves.iter().map(String::as_str)); } @@ -3194,23 +3186,23 @@ mod tests { } #[test] - fn an_installed_app_receives_only_names_init_holds() { + fn an_installed_app_receives_only_names_the_supervisor_holds() { for cfg in ALL_CONFIGS { apps_receive_a_served_name(&load(cfg)).unwrap_or_else(|e| panic!("{cfg}: {e}")); } let provided: SystemConfig = toml::from_str( - "init = []\n[apps]\nreceives = [\"surface\"]\n\ + "[apps]\nreceives = [\"surface\"]\n\ [programs.terminal]\nprovides = [\"surface\"]\n", ) .unwrap(); assert!(apps_receive_a_served_name(&provided).is_err()); let ghost: SystemConfig = - toml::from_str("init = []\n[apps]\nreceives = [\"ghost\"]\n").unwrap(); + toml::from_str("[apps]\nreceives = [\"ghost\"]\n").unwrap(); assert!(apps_receive_a_served_name(&ghost).is_err()); } /// A `serves` name is one port machine-wide; a `provides` name is one port - /// per instance. A name declared both ways is a config where init makes a + /// per instance. A name declared both ways is a config where the supervisor makes a /// port nobody accepts from while the real one is made elsewhere. fn provides_disjoint_from_serves(cfg: &SystemConfig) -> Result<(), String> { let serves: Vec<&str> = cfg @@ -3236,13 +3228,13 @@ mod tests { provides_disjoint_from_serves(&load(cfg)).unwrap_or_else(|e| panic!("{cfg}: {e}")); } let bad: SystemConfig = toml::from_str( - "init = []\n[programs.a]\nserves = [\"x\"]\n[programs.b]\nprovides = [\"x\"]\n", + "[programs.a]\nserves = [\"x\"]\n[programs.b]\nprovides = [\"x\"]\n", ) .unwrap(); assert!(provides_disjoint_from_serves(&bad).is_err()); } - /// Init mints one claim per device, so a config naming one twice starts a + /// The supervisor mints one claim per device, so a config naming one twice starts a /// program with a hole where its claim should be. fn one_claimant_per_device(cfg: &SystemConfig) -> Result<(), String> { let mut seen: BTreeMap<&str, &str> = BTreeMap::new(); @@ -3267,32 +3259,32 @@ mod tests { one_claimant_per_device(&load(cfg)).unwrap_or_else(|e| panic!("{cfg}: {e}")); } let bad: SystemConfig = toml::from_str( - "init = []\n[programs.a]\ndevices = [\"framebuffer\"]\n\ + "[programs.a]\ndevices = [\"framebuffer\"]\n\ [programs.b]\ndevices = [\"framebuffer\"]\n", ) .unwrap(); assert!(one_claimant_per_device(&bad).is_err()); } - /// netd's actuator that only its Intel driver answers, spelled here and - /// held to netd's own declaration by - /// [`netd_declares_the_flag_this_gate_spells`]. + /// netstack's actuator that only its Intel driver answers, spelled here and + /// held to netstack's own declaration by + /// [`netstack_declares_the_flag_this_gate_spells`]. const EXIT_WITH_LEASE: &str = "--exit-with-lease"; - /// netd's main module, which is where both halves of this gate's spelling + /// netstack's main module, which is where both halves of this gate's spelling /// live: nothing links the two crates, so the build system reads the source. - fn netd_source() -> (std::path::PathBuf, String) { - let at = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("userland/netd/src/main.rs"); - let text = std::fs::read_to_string(&at).expect("netd's main module"); + fn netstack_source() -> (std::path::PathBuf, String) { + let at = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("userland/netstack/src/main.rs"); + let text = std::fs::read_to_string(&at).expect("netstack's main module"); (at, text) } - /// Nothing links the two crates: netd is a userland binary and this is the - /// build system, so the flags both ends spell are held to netd's own + /// Nothing links the two crates: netstack is a userland binary and this is the + /// build system, so the flags both ends spell are held to netstack's own /// declarations by reading its source. #[test] - fn netd_declares_the_flag_this_gate_spells() { - let (at, source) = netd_source(); + fn netstack_declares_the_flag_this_gate_spells() { + let (at, source) = netstack_source(); assert!( crate::bootlog::declares(&source, &format!("\"{EXIT_WITH_LEASE}\"")), "{} declares no constant equal to \"{EXIT_WITH_LEASE}\"", @@ -3307,14 +3299,14 @@ mod tests { (digits.len() == 4).then_some(digits) } - /// The device entries netd opens with the driver that has §10.2.4.4's `ICS`, - /// read out of netd's own `CARDS` rather than guessed from a vendor id: each + /// The device entries netstack opens with the driver that has §10.2.4.4's `ICS`, + /// read out of netstack's own `CARDS` rather than guessed from a vendor id: each /// row spells an id and the constructor that takes it on one line. /// /// **The scan reaches that one spelling and no other**, so every /// `Card::intel` row it saw has to have yielded an id — a table written /// another way reds here instead of narrowing this gate to nothing. - fn netd_intel_cards(source: &str) -> Vec { + fn netstack_intel_cards(source: &str) -> Vec { let mut cards = Vec::new(); let mut rows = 0; for line in source.lines() { @@ -3331,16 +3323,16 @@ mod tests { assert_eq!( cards.len(), rows, - "netd names `Card::intel` on {rows} line(s) and an id was read off {}; its `CARDS` \ + "netstack names `Card::intel` on {rows} line(s) and an id was read off {}; its `CARDS` \ table is spelled in a way this gate does not reach", cards.len() ); cards } - /// netd's Intel-only actuators — `--exit-with-lease` reports the Intel + /// netstack's Intel-only actuators — `--exit-with-lease` reports the Intel /// driver's bring-up beside the lease — and virtio's driver has none, so a - /// boot config that arms one on a card netd opens with any other driver is + /// boot config that arms one on a card netstack opens with any other driver is /// a boot that panics instead of answering the question it was built for. fn an_armed_intel_actuator_claims_a_card_the_driver_opens( cfg: &SystemConfig, @@ -3353,7 +3345,7 @@ mod tests { if !prog.devices.iter().any(|d| cards.contains(d)) { return Err(format!( "`{name}` is armed with `{EXIT_WITH_LEASE}` and claims {:?}, none of which \ - is one of the {cards:?} netd opens with that driver", + is one of the {cards:?} netstack opens with that driver", prog.devices )); } @@ -3363,9 +3355,9 @@ mod tests { #[test] fn every_armed_intel_actuator_claims_a_card_the_driver_opens() { - let (_, source) = netd_source(); - let cards = netd_intel_cards(&source); - assert!(!cards.is_empty(), "netd's `CARDS` names no card its Intel driver opens"); + let (_, source) = netstack_source(); + let cards = netstack_intel_cards(&source); + assert!(!cards.is_empty(), "netstack's `CARDS` names no card its Intel driver opens"); let mut armed = 0; for cfg in ALL_CONFIGS { let config = load(cfg); @@ -3382,12 +3374,12 @@ mod tests { assert!(armed > 0, "no shipped boot config arms `{EXIT_WITH_LEASE}` at all"); let armed_on = |device: &str, args: &str| { let cfg: SystemConfig = toml::from_str(&format!( - "init = []\n[programs.netd]\ndevices = [\"{device}\"]\nargs = [{args}]\n" + "[programs.netstack]\ndevices = [\"{device}\"]\nargs = [{args}]\n" )) .unwrap(); an_armed_intel_actuator_claims_a_card_the_driver_opens(&cfg, &cards) }; - // The card netd drives with the other driver, and an Intel function it + // The card netstack drives with the other driver, and an Intel function it // drives with none: a vendor id is not what gives a part an `ICS` or a // PHY behind `MDIC`. let flag = format!("\"{EXIT_WITH_LEASE}\""); @@ -3396,13 +3388,13 @@ mod tests { assert!(armed_on(&cards[0], &flag).is_ok()); } - /// A device name the ABI does not know renders fine and leaves init with a + /// A device name the ABI does not know renders fine and leaves the supervisor with a /// `devices` entry it cannot mint — a dead machine for a typo, where this is /// a red in milliseconds. Same for a `syscap` right. /// /// The ABI's own parser, not a copy of it: a `pci::` entry /// names a function and a class name names a class, and this is the same - /// `DeviceRequest::parse` init and the kernel read the entry with. + /// `DeviceRequest::parse` the supervisor and the kernel read the entry with. fn names_only_real_capabilities(cfg: &SystemConfig) -> Result<(), String> { for (name, prog) in &cfg.programs { for device in &prog.devices { @@ -3444,7 +3436,7 @@ mod tests { } /// The diagnostic image's whole reason for existing: nothing in it can claim - /// the framebuffer, so the kernel's boot log stays on the panel. `/system/bin/init` + /// the framebuffer, so the kernel's boot log stays on the panel. `/system/bin/supervisor` /// is in every image and could reach a device, so the property becomes "the /// config declares no `devices`" — checkable here for the first time. #[test] @@ -3452,12 +3444,12 @@ mod tests { claims_no_device(&load("diag/system.toml")) .unwrap_or_else(|e| panic!("diag/system.toml: {e}")); let bad: SystemConfig = - toml::from_str("init = []\n[programs.x]\ndevices = [\"framebuffer\"]\n").unwrap(); + toml::from_str("[programs.x]\ndevices = [\"framebuffer\"]\n").unwrap(); assert!(claims_no_device(&bad).is_err()); } /// `[boot] start` names program keys, so a typo is a build error rather than - /// a refusal `/system/bin/init` reports at boot. + /// a refusal `/system/bin/supervisor` reports at boot. fn started_programs_are_declared(cfg: &SystemConfig) -> Result<(), String> { for name in &cfg.boot.start { if !cfg.programs.contains_key(name) { @@ -3472,7 +3464,7 @@ mod tests { for cfg in ALL_CONFIGS { started_programs_are_declared(&load(cfg)).unwrap_or_else(|e| panic!("{cfg}: {e}")); } - let bad: SystemConfig = toml::from_str("init = []\n[boot]\nstart = [\"ghost\"]\n").unwrap(); + let bad: SystemConfig = toml::from_str("[boot]\nstart = [\"ghost\"]\n").unwrap(); assert!(started_programs_are_declared(&bad).is_err()); } @@ -3486,7 +3478,7 @@ mod tests { let programs = declared(&["shell"]); let started = ["shell".to_string()]; assert!(unnamed_program( - &["bin/init", "bin/shell", "lib/libtls_lib.so", "etc/system.manifest"], + &["bin/supervisor", "bin/shell", "lib/libtls_lib.so", "etc/system.manifest"], &programs, &started, ) @@ -3515,10 +3507,10 @@ mod tests { /// carries. The day the check learns it, this reds. #[test] fn the_check_does_not_reach_a_spawner_that_never_spawns() { - // `logd` spawns nothing in any config this tree ships. - let programs = declared(&["logd"]); + // `logkeeper` spawns nothing in any config this tree ships. + let programs = declared(&["logkeeper"]); assert!( - unnamed_program(&["bin/test_rs_window_child"], &programs, &["logd".to_string()]) + unnamed_program(&["bin/test_rs_window_child"], &programs, &["logkeeper".to_string()]) .is_ok(), "the scan now reaches whether the spawner spawns; correct this test and its header" ); diff --git a/src/ci.rs b/src/ci.rs index cbffbcdc617..c6e5aca2c9b 100644 --- a/src/ci.rs +++ b/src/ci.rs @@ -1061,7 +1061,7 @@ mod tests { let programs = [ program("calc", Host::App(Vec::new())), program("doom", Host::App(vec![Os::Windows])), - program("init", Host::Exempt), + program("supervisor", Host::Exempt), ]; let judged = |os| { let (attempted, declared) = attempted(&programs, os); diff --git a/src/hostws.rs b/src/hostws.rs index 96764964819..c7dbd21d97e 100644 --- a/src/hostws.rs +++ b/src/hostws.rs @@ -186,9 +186,7 @@ fn unclaimed(members: &BTreeSet, found: &BTreeSet) -> Vec BTreeSet { let mut all: BTreeSet = members(root).into_iter().filter(|m| m != ".").collect(); @@ -423,12 +421,7 @@ mod tests { /// into its workspace root's target directory, so such a path is one that /// cannot exist. /// - /// Every workspace in the tree, not just this one: the first thing this - /// found after `userland/doom/build.rs` was `host-tests.yml` caching - /// `userland/sshd/target`, which has never been a directory — `sshd` is a - /// member of `userland/`'s workspace and builds into `userland/target`. A - /// cache path that matches nothing fails silently and forever, which is why - /// it survived. + /// Every workspace in the tree, not just this one. /// /// The files scanned are the ones that *act* on a path: the workflows, this /// build system, and every `build.rs` in the tree. Prose is left alone — @@ -489,10 +482,10 @@ mod tests { assert!(dead_member_target_paths(&members, "userland/target").is_empty()); // A member of the userland workspace, which is the real find above. let with_userland: BTreeSet = - members.union(&["userland/sshd".to_string()].into()).cloned().collect(); + members.union(&["userland/sshserver".to_string()].into()).cloned().collect(); assert_eq!( - dead_member_target_paths(&with_userland, " userland/sshd/target\n"), - ["userland/sshd/target"], + dead_member_target_paths(&with_userland, " userland/sshserver/target\n"), + ["userland/sshserver/target"], ); // And the root's own `target` is where members build *to*. assert!(dead_member_target_paths(&members, "root.join(\"target\")").is_empty()); diff --git a/src/image.rs b/src/image.rs index a4a3a897a86..68e82bda228 100644 --- a/src/image.rs +++ b/src/image.rs @@ -428,7 +428,7 @@ fn round_up_sectors(n: usize) -> usize { /// /// A correctness requirement rather than tidiness. Every block service /// transfers whole 4 KiB blocks and each file server keeps its own cached -/// copies of the blocks it has touched (`userland/fsd`); two partitions +/// copies of the blocks it has touched (`userland/fileserver`); two partitions /// sharing one device block would make each other's copies stale with /// nothing able to notice. 1 MiB rather than the 4096 the kernel needs, /// because that is what every partitioner uses and what an erase block wants. @@ -628,7 +628,7 @@ fn create_slot_volume(image: Option<&Sections>, bytes: usize) -> Vec { /// The partition the kernel's log lives on, empty until a machine boots. /// /// Exactly [`FAT32_MIN_BYTES`], because the floor is not ours to choose and the -/// log cannot use much of it: sixteen boots at `/system/bin/logd`'s `MAX_LOG_BYTES` +/// log cannot use much of it: sixteen boots at `/system/bin/logkeeper`'s `MAX_LOG_BYTES` /// come to 16 MiB, under half of what this volume has free, and there is no /// smaller FAT32 to cut it down to. fn create_log_volume() -> Vec { @@ -963,7 +963,7 @@ mod tests { /// A ROOT image with one file in it, for the tests that need a real one /// rather than a placeholder: the assembler reads its superblock. fn tiny_root() -> Vec { - create_root_image(&[("bin/init".to_string(), b"init".to_vec())], &[], true) + create_root_image(&[("bin/supervisor".to_string(), b"supervisor".to_vec())], &[], true) } /// A fixed key: what these tests judge is the image, not whose it is. @@ -1175,9 +1175,9 @@ mod tests { #[test] fn one_ordering_of_one_set_is_one_image() { let files: Vec<(String, Vec)> = vec![ - ("bin/init".to_string(), b"init-binary".to_vec()), + ("bin/supervisor".to_string(), b"supervisor-binary".to_vec()), ("bin/toybox".to_string(), (0..40_000u32).map(|i| (i ^ 0x5A) as u8).collect()), - ("etc/system.manifest".to_string(), b"[start]\ninit\n".to_vec()), + ("etc/system.manifest".to_string(), b"[start]\nsupervisor\n".to_vec()), ("share/empty".to_string(), Vec::new()), ]; let symlinks = vec![ @@ -1230,11 +1230,11 @@ mod tests { #[test] fn the_root_partition_reads_back_as_the_files_the_build_put_in_it() { let files: Vec<(String, Vec)> = vec![ - ("bin/init".to_string(), b"init-binary".to_vec()), + ("bin/supervisor".to_string(), b"supervisor-binary".to_vec()), // Multi-block, so an extent list that stopped after the first is // caught by the hash rather than by the size. ("bin/toybox".to_string(), (0..40_000u32).map(|i| (i ^ 0x5A) as u8).collect()), - ("etc/system.manifest".to_string(), b"[start]\ninit\n".to_vec()), + ("etc/system.manifest".to_string(), b"[start]\nsupervisor\n".to_vec()), ("share/empty".to_string(), Vec::new()), ]; let symlinks = vec![("bin/ls".to_string(), "/system/bin/toybox".to_string())]; @@ -1303,8 +1303,8 @@ mod tests { /// ROOT by type where the table says, `bcachefs` mounts it, and /// `toyos-manifest` parses the records out of the volume. /// - /// `INIT_PATH` comes from the kernel source, and that is a **text scan of - /// one spelling** — the `pub const INIT_PATH: &str = "…";` line — so a + /// `SUPERVISOR_PATH` comes from the kernel source, and that is a **text scan of + /// one spelling** — the `pub const SUPERVISOR_PATH: &str = "…";` line — so a /// kernel computing its spawn path otherwise is walked past. Not finding /// the line fails here rather than skipping. #[test] @@ -1322,7 +1322,7 @@ mod tests { .iter() .map(|p| (under_system(&p.path).to_string(), b"placeholder".to_vec())) .collect(); - files.push(("bin/init".to_string(), b"init".to_vec())); + files.push(("bin/supervisor".to_string(), b"supervisor".to_vec())); files.push((toyos_manifest::PATH.to_string(), manifest.clone())); let disk = create_boot_image( @@ -1355,19 +1355,19 @@ mod tests { "the path a process opens is not where ROOT carries the manifest" ); - let init = init_path_of_the_kernel(root); + let supervisor = supervisor_path_of_the_kernel(root); let names: std::collections::BTreeSet = fs .list(usize::MAX, &|_| true) .expect("list the ROOT partition") .into_iter() .map(|(name, _)| name) .collect(); - for path in std::iter::once(&init).chain(declared.programs.iter().map(|p| &p.path)) { + for path in std::iter::once(&supervisor).chain(declared.programs.iter().map(|p| &p.path)) { let name = under_system(path); assert_ne!(name, path.as_str(), "{path} is not under the mount ROOT gets"); assert!(names.contains(name), "ROOT has no {name} for the declared path {path}"); } - assert!(names.contains("bin/init"), "ROOT carries {names:?} and no bin/init"); + assert!(names.contains("bin/supervisor"), "ROOT carries {names:?} and no bin/supervisor"); } /// A declared absolute path as ROOT carries it; unchanged off that mount. @@ -1375,15 +1375,15 @@ mod tests { path.strip_prefix("/system/").unwrap_or(path) } - /// The literal in `kernel/src/loader/mod.rs`'s `INIT_PATH`. - fn init_path_of_the_kernel(root: &Path) -> String { - const ITEM: &str = "pub const INIT_PATH: &str = \""; + /// The literal in `kernel/src/loader/mod.rs`'s `SUPERVISOR_PATH`. + fn supervisor_path_of_the_kernel(root: &Path) -> String { + const ITEM: &str = "pub const SUPERVISOR_PATH: &str = \""; let source = std::fs::read_to_string(root.join("kernel/src/loader/mod.rs")) .expect("kernel/src/loader/mod.rs"); source .lines() .find_map(|line| line.trim_start().strip_prefix(ITEM)?.split('"').next()) - .expect("no `pub const INIT_PATH: &str = \"…\";` in kernel/src/loader/mod.rs") + .expect("no `pub const SUPERVISOR_PATH: &str = \"…\";` in kernel/src/loader/mod.rs") .to_string() } } diff --git a/src/kernelconsole.rs b/src/kernelconsole.rs index e23b8634990..f90197e1f23 100644 --- a/src/kernelconsole.rs +++ b/src/kernelconsole.rs @@ -93,7 +93,7 @@ mod tests { #[test] fn a_port_the_firmware_left_alone_passes_whole() { - let later = format!("{KERNEL}{{1.002 init}} init: a program's line\n"); + let later = format!("{KERNEL}{{1.002 supervisor}} supervisor: a program's line\n"); assert_eq!(passed(&later, &[3, 40]), later); } diff --git a/src/lan.rs b/src/lan.rs index 66aaa5029eb..3808999f599 100644 --- a/src/lan.rs +++ b/src/lan.rs @@ -12,14 +12,14 @@ use std::net::Ipv4Addr; use crate::bootlog::message; /// The records both arms are written against, spelled once. -pub const MAC: &str = "netd: MAC "; -const LEASE: &str = "netd: DHCP: lease "; -pub const LINK_UP: &str = "netd: I219: link up at "; -pub const READY: &str = "netd: ready, at most "; +pub const MAC: &str = "netstack: MAC "; +const LEASE: &str = "netstack: DHCP: lease "; +pub const LINK_UP: &str = "netstack: I219: link up at "; +pub const READY: &str = "netstack: ready, at most "; /// The name this machine asks its network to record for it, and answers for as -/// `.local`; held to netd's own `dhcp::HOSTNAME` by -/// [`tests::netd_declares_the_name_this_module_spells`]. +/// `.local`; held to netstack's own `dhcp::HOSTNAME` by +/// [`tests::netstack_declares_the_name_this_module_spells`]. pub const HOSTNAME: &str = "toyos-t14"; /// One lease, as the record carries it. @@ -30,7 +30,7 @@ pub struct Lease { pub server: Ipv4Addr, pub gateway: Ipv4Addr, pub dns: Vec, - /// Milliseconds between netd starting and the lease landing. + /// Milliseconds between netstack starting and the lease landing. pub ms: u64, } @@ -64,7 +64,7 @@ pub fn lease_in(text: &str) -> Result { server: address("the server's address", after(" from ", ",")?)?, gateway: address("the gateway's address", after(", gateway ", ",")?)?, dns, - ms: after("], ", " ms after netd came up")? + ms: after("], ", " ms after netstack came up")? .parse() .map_err(|_| unreadable("a millisecond count"))?, }) @@ -86,9 +86,9 @@ pub fn link_up_ms(text: &str) -> Result { .map_err(|_| format!("{line:?} carries no readable link-up time")) } -/// What netd wrote in a boot's `/log`: the text of each of its lines. -pub fn netd_records(text: &str) -> String { - crate::bootlog::lines_of(text, "netd") +/// What netstack wrote in a boot's `/log`: the text of each of its lines. +pub fn netstack_records(text: &str) -> String { + crate::bootlog::lines_of(text, "netstack") } /// The T14's I219, as the kernel's hand-over record spells its id. @@ -182,17 +182,17 @@ pub fn delivered(text: &str) -> Result { mod tests { use super::*; - const LEASED: &str = "[2026-09-08 16:08:23 2.100 cpu0] netd: DHCP: lease 10.0.2.15/24 from \ - 10.0.2.2, gateway 10.0.2.2, dns [10.0.2.3 10.0.2.4], 412 ms after netd \ + const LEASED: &str = "[2026-09-08 16:08:23 2.100 cpu0] netstack: DHCP: lease 10.0.2.15/24 from \ + 10.0.2.2, gateway 10.0.2.2, dns [10.0.2.3 10.0.2.4], 412 ms after netstack \ came up"; - /// Nothing links the two crates: netd is a `no_std`-shaped userland binary + /// Nothing links the two crates: netstack is a `no_std`-shaped userland binary /// and this is the build system, so the name both ends spell is held to - /// netd's own declaration by reading its source. + /// netstack's own declaration by reading its source. #[test] - fn netd_declares_the_name_this_module_spells() { - let at = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("userland/netd/src/dhcp.rs"); - let source = std::fs::read_to_string(&at).expect("netd's dhcp module"); + fn netstack_declares_the_name_this_module_spells() { + let at = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("userland/netstack/src/dhcp.rs"); + let source = std::fs::read_to_string(&at).expect("netstack's dhcp module"); assert!( crate::bootlog::declares(&source, &format!("\"{HOSTNAME}\"")), "{} declares no constant equal to \"{HOSTNAME}\"", @@ -243,23 +243,23 @@ mod tests { assert!(why.contains("a millisecond count"), "{why}"); } - /// netd's lines and nothing else: a kernel record spelled like netd's, - /// another program's line quoting netd's head, and a console line with no + /// netstack's lines and nothing else: a kernel record spelled like netstack's, + /// another program's line quoting netstack's head, and a console line with no /// head at all are each left out. #[test] - fn only_netds_own_lines_are_netds() { + fn only_netstacks_own_lines_are_netstacks() { let lease = LEASED.split_once("] ").expect("a record").1; let log = format!( - "{{2026-09-08 16:08:23 2.100 netd}} {lease}\n\ - {{2026-09-08 16:08:23 2.200 netd}} netd: ready, at most 8 clients\n\ - {{2026-09-08 16:08:23 2.300 evil}} {{2026-09-08 16:08:23 2.300 netd}} netd: MAC 00:00:00:00:00:00\n\ - [2026-09-08 16:08:23 2.400 cpu0] netd: MAC 00:00:00:00:00:01\n\ - netd: MAC 52:54:00:12:34:56\n" + "{{2026-09-08 16:08:23 2.100 netstack}} {lease}\n\ + {{2026-09-08 16:08:23 2.200 netstack}} netstack: ready, at most 8 clients\n\ + {{2026-09-08 16:08:23 2.300 evil}} {{2026-09-08 16:08:23 2.300 netstack}} netstack: MAC 00:00:00:00:00:00\n\ + [2026-09-08 16:08:23 2.400 cpu0] netstack: MAC 00:00:00:00:00:01\n\ + netstack: MAC 52:54:00:12:34:56\n" ); - let netd = netd_records(&log); - assert_eq!(netd.lines().count(), 2, "{netd}"); - assert!(lease_in(&netd).is_ok()); - assert!(!netd.contains(MAC), "a line quoting netd was read as netd's: {netd}"); + let netstack = netstack_records(&log); + assert_eq!(netstack.lines().count(), 2, "{netstack}"); + assert!(lease_in(&netstack).is_ok()); + assert!(!netstack.contains(MAC), "a line quoting netstack was read as netstack's: {netstack}"); } #[test] @@ -277,7 +277,7 @@ mod tests { [2026-09-16 15:01:20 1.333 cpu0] pcidev: PCI 00:1f.6 [8086:15fc] handed over on slot 0, vector 0x28 [2026-09-16 15:01:20 1.360 cpu0] ELF: 3417 relocations indexed (RELATIVE + GLOB_DAT + TPOFF) [2026-09-16 15:01:20 1.360 cpu0] spawn: TLS 1 modules, total_memsz=144 -[2026-09-16 15:01:20 1.518 cpu0] spawn: /system/bin/netd pid=5 tid=0 dst=5 base=0x10000000000 entry=0x1000004e5c0 cr3=0x1cc1000 symbols=2048KiB (layout=25ms relocs=0ms deps=0ms tls=1ms total=184ms) +[2026-09-16 15:01:20 1.518 cpu0] spawn: /system/bin/netstack pid=5 tid=0 dst=5 base=0x10000000000 entry=0x1000004e5c0 cr3=0x1cc1000 symbols=2048KiB (layout=25ms relocs=0ms deps=0ms tls=1ms total=184ms) [2026-09-16 15:01:20 1.552 cpu0] ELF: 2833 relocations indexed (RELATIVE + GLOB_DAT + TPOFF) [2026-09-16 15:01:20 1.552 cpu0] spawn: TLS 1 modules, total_memsz=144 [2026-09-16 15:01:20 1.739 cpu0] spawn: /system/bin/test-runner pid=6 tid=0 dst=6 base=0x10000000000 entry=0x1000001fff0 cr3=0x1cbf000 symbols=2048KiB (layout=32ms relocs=0ms deps=0ms tls=2ms total=221ms) @@ -319,7 +319,7 @@ mod tests { /// Another writer's line carrying the words is not the kernel's record. #[test] fn a_line_that_is_not_the_kernels_record_is_refused_and_named() { - let stray = "[2026-09-16 15:01:21 2.240 cpu3] test-runner: waiting until netd took its \ + let stray = "[2026-09-16 15:01:21 2.240 cpu3] test-runner: waiting until netstack took its \ first message\n"; let log = edited(TOOK, "").replacen( "total=184ms)\n", @@ -330,7 +330,7 @@ mod tests { let why = delivered(&log).expect_err("a userland line"); assert!(why.contains("no kernel record"), "{why}"); assert!(why.contains("a line not in the kernel's spelling of the record: "), "{why}"); - assert!(why.contains("test-runner: waiting until netd"), "{why}"); + assert!(why.contains("test-runner: waiting until netstack"), "{why}"); } #[test] @@ -397,7 +397,7 @@ mod tests { /// hand-over. #[test] fn a_hand_over_not_in_the_kernels_spelling_is_refused() { - let stray = "[2026-09-16 15:01:20 1.333 cpu0] netd: [8086:15fc] handed over on slot 0, \ + let stray = "[2026-09-16 15:01:20 1.333 cpu0] netstack: [8086:15fc] handed over on slot 0, \ vector 0x28\n"; let why = delivered(&edited(HANDED, stray)).expect_err("a userland line"); assert!(why.contains("no `[8086:15fc] handed over on slot ` record"), "{why}"); diff --git a/src/metal.rs b/src/metal.rs index 67e36901371..9199546e3af 100644 --- a/src/metal.rs +++ b/src/metal.rs @@ -30,7 +30,7 @@ const CONNECT_SECS: u64 = 10; /// How long the machine has to go quiet after `reboot`. const GOING_DOWN_SECS: u64 = 120; -/// What the machine spends getting back to `sshd` once a ToyOS boot is over: +/// What the machine spends getting back to Ubuntu's ssh server once a ToyOS boot is over: /// the firmware's pass and Ubuntu's own boot. const RETURN_ALLOWANCE_SECS: u64 = 300; @@ -165,7 +165,7 @@ pub enum Refusal { /// **The loader reported a record and booted no kernel.** Not the same thing /// as an absent boot record, and the difference is the whole diagnosis: the /// pass that reads the black box ends the chain by design, so a machine that - /// came back with `loader.log` carrying a reporting pass and `logd` carrying + /// came back with `loader.log` carrying a reporting pass and `logkeeper` carrying /// nothing did exactly what it was told — the question is why it had a /// record to report at all. ReportedAndBootedNothing { said: String }, @@ -189,7 +189,7 @@ pub enum Refusal { /// or the reader of the log the boot serves. Cable(String), /// **What a swap of a running machine's service came to is not the new - /// binary in service**: init's words, the machine's answer or ssh + /// binary in service**: the supervisor's words, the machine's answer or ssh /// afterwards, each finding by name. Swap(Vec), /// The machine did not name itself: its SMBIOS answer is not @@ -333,7 +333,7 @@ impl fmt::Display for Refusal { Self::ReportedAndBootedNothing { said } => write!( f, "the loader reported a record and booted no kernel: `loader.log` carries a \ - pass that read the black box and ended the chain, and `logd` wrote nothing \ + pass that read the black box and ended the chain, and `logkeeper` wrote nothing \ because nothing ran. This boot measured no test. What the pass said was: \ {said}" ), @@ -605,7 +605,7 @@ impl Target { Job::Wipe => literal(&[WIPEFS, "--all", &node]), Job::Flash => literal(&[DD, &of, "bs=4M", "conv=fsync"]), // The log partition read whole, as bytes rather than as files: what - // `toyos-fat32-check` judges is the volume `logd` wrote, and a + // `toyos-fat32-check` judges is the volume `logkeeper` wrote, and a // `mount` has already had a driver's opinion about it. Read-only, and // the partition is the only node named, spelled from the disk's. Job::ReadLog => literal(&[DD, &read_log, "bs=4M"]), @@ -1296,9 +1296,9 @@ impl Driver { ) } - /// The loader's own file, and then everything `logd` wrote, in name order: + /// The loader's own file, and then everything `logkeeper` wrote, in name order: /// a freshly flashed volume holds one boot's files, and its newest file - /// alone would miss the continuations `logd` rotates into. + /// alone would miss the continuations `logkeeper` rotates into. /// /// Two strings and not one, because only the second is the boot's log and /// [`bootlog::verdict`] is about that. @@ -1325,15 +1325,15 @@ impl Driver { fn read_mounted(&self) -> Result<(String, String), Refusal> { let at = shell_word(&self.target.mount); let listing = self.ssh("listing the log", &format!("ls -1 {at}"))?; - let (loader, logd) = bootlog::split_listing(&listing); + let (loader, logkeeper) = bootlog::split_listing(&listing); // Absence is an answer and not a failure: the boot is judged on what - // `logd` wrote either way. + // `logkeeper` wrote either way. let loader = match loader { Some(name) => self.cat(name)?, None => format!("{}: the loader wrote none\n", bootlog::LOADER_LOG), }; let mut text = String::new(); - for name in logd { + for name in logkeeper { text.push_str(&self.cat(name)?); } Ok((loader, text)) @@ -1679,7 +1679,7 @@ impl Talking { /// reboot conversation — a swap's own exchange /// ([`crate::metalswap::swap`]). /// - /// A swap of the netd carrying it is followed across by + /// A swap of the netstack carrying it is followed across by /// [`crate::metalswap::swap`] itself ([`crate::metaltalk::Stream::redial`]). fn connect(&self, file: &str, by: std::time::Duration) -> Result { let peer = crate::metaltalk::Peer::Named { @@ -1697,13 +1697,13 @@ impl Talking { pub const READBACK_SWAP_STREAM: &str = "swap-stream.log"; /// Replace `service`'s binary on the machine that answers for its own name, -/// and judge it: the machine is asked over ssh, init's words are read off the +/// and judge it: the machine is asked over ssh, the supervisor's words are read off the /// log stream, and ssh must answer again afterwards. /// /// **Nothing is flashed and nothing is rebooted**: the machine is found at /// `toyos-t14.local` the way [`Talking::start`] finds it, so this can be /// started before that machine has booted or long after — and read on across -/// a swap of netd itself ([`crate::metalswap::swap`]). +/// a swap of netstack itself ([`crate::metalswap::swap`]). fn swap_running(args: &Args, service: &str) -> Result<(), Refusal> { let (Some(key), Some(dir), Some(binary)) = (&args.talk, &args.readback, &args.binary) else { return Err(Refusal::Usage("--swap wants --talk, --readback and --binary".into())); @@ -1726,7 +1726,7 @@ fn swap_running(args: &Args, service: &str) -> Result<(), Refusal> { stream.give_up(); let swapped = swapped.map_err(|why| Refusal::Swap(vec![why]))?; for (word, detail) in &swapped.words { - println!(" init: {}: {detail}", word.as_str()); + println!(" supervisor: {}: {detail}", word.as_str()); } for line in &swapped.said { print!(" {service}| {line}"); @@ -2296,7 +2296,7 @@ fn boot_file(back: u64, stick: u64, machine: &Machine, wire: Option<&Wire>) -> S /// pass that ended the chain; the loader never reached its handoff line, which /// is what a pass that *did* boot a kernel writes; and the kernel log carries no /// boot record. A boot whose kernel died early has the handoff line and no -/// chain-end; a boot that panicked has both, and a `logd` file besides. +/// chain-end; a boot that panicked has both, and a `logkeeper` file besides. /// /// It exists because `Unfit::NoBootRecord` says "this boot failed" where the /// answer is "this boot never happened", and the two send a reader to different @@ -2534,10 +2534,10 @@ mod tests { /// swap is no swap. #[test] fn a_swap_is_not_a_boot_and_names_what_it_acts_with() { - let whole = ["--swap", "netd", "--binary", "n", "--talk", "/tmp/k", "--readback", "/tmp/r"] + let whole = ["--swap", "netstack", "--binary", "n", "--talk", "/tmp/k", "--readback", "/tmp/r"] .map(String::from); let args = Args::parse(&whole).expect("a whole swap"); - assert_eq!(args.swap.as_deref(), Some("netd")); + assert_eq!(args.swap.as_deref(), Some("netstack")); for flag in [ vec!["--fat32-check"], @@ -2563,7 +2563,7 @@ mod tests { let lone = ["--binary", "n"].map(String::from); assert!(Args::parse(&lone).unwrap_err().to_string().contains("--swap")); let mut bent = whole.to_vec(); - bent[1] = "../netd".to_string(); + bent[1] = "../netstack".to_string(); assert!(Args::parse(&bent).unwrap_err().to_string().contains("no service")); } @@ -2748,7 +2748,7 @@ mod tests { bootlog::CHAIN_ENDS_LINE, ); let log = format!( - "[kernel 1.151 cpu0] Boot: complete (1151ms)\n{{1.203 init}} {} (Reboot)\n", + "[kernel 1.151 cpu0] Boot: complete (1151ms)\n{{1.203 supervisor}} {} (Reboot)\n", bootlog::STOPPING ); assert_eq!( @@ -3353,7 +3353,7 @@ mod tests { bootlog::SEPARATOR ); let log = "[2026-09-29 10:36:53 1.171 cpu0] Boot: complete (1171ms)\n\ - {2026-09-29 10:36:53 1.186 init} init: power: the machine stops, and logd makes \ + {2026-09-29 10:36:53 1.186 supervisor} supervisor: power: the machine stops, and logkeeper makes \ the log whole first (Reboot)\n"; let armed = |names: &[&str]| -> Vec { names.iter().map(|n| (*n).to_string()).collect() }; assert_eq!( diff --git a/src/metaldevices.rs b/src/metaldevices.rs index 95a5ac2c538..f8321467060 100644 --- a/src/metaldevices.rs +++ b/src/metaldevices.rs @@ -2,7 +2,7 @@ //! the black box. //! //! **Text in, verdicts out.** Everything here reads the two strings -//! `src/metal.rs` brings back off the stick — the loader's file and `logd`'s — +//! `src/metal.rs` brings back off the stick — the loader's file and `logkeeper`'s — //! and nothing here touches a machine. #![forbid(unsafe_code)] diff --git a/src/metalimage.rs b/src/metalimage.rs index 36bc686ba5c..31a0ce94e14 100644 --- a/src/metalimage.rs +++ b/src/metalimage.rs @@ -11,7 +11,7 @@ //! it. The derivation is here, pure, because what it changes about the config //! is what the T14 sees and nothing else may drift from it: the one authority a //! `reboot` job needs (the `power` connector, which the applet inherits with the -//! runner's namespace and asks init through), the applet itself, and the name +//! runner's namespace and asks the supervisor through), the applet itself, and the name //! that reaches it. #![forbid(unsafe_code)] @@ -25,7 +25,7 @@ const TOYBOX: &str = "toybox"; const REBOOT_LINK: &str = "bin/reboot"; const TOYBOX_PATH: &str = "/system/bin/toybox"; -/// The connector the last job needs: init's `power` port, which has `logd` +/// The connector the last job needs: the supervisor's `power` port, which has `logkeeper` /// make the log whole and then resets the machine. const POWER: &str = "power"; @@ -188,20 +188,20 @@ mod tests { let receives = parsed["programs"][RUNNER]["receives"].as_array().unwrap(); assert_eq!(receives.iter().filter(|r| r.as_str() == Some(POWER)).count(), 1); assert_eq!(parsed["symlinks"]["bin/echo"].as_str(), Some(TOYBOX_PATH)); - assert!(parsed["programs"].get("soundd").is_some()); + assert!(parsed["programs"].get("soundserver").is_some()); } /// A config with nothing to run a job is refused by name rather than /// producing an image that parks the machine for 360 s. #[test] fn a_config_with_no_runner_is_refused_by_name() { - let refusal = derive("[boot]\nstart = [\"logd\"]\n", &[], &[]).unwrap_err(); + let refusal = derive("[boot]\nstart = [\"logkeeper\"]\n", &[], &[]).unwrap_err(); assert_eq!(refusal, Underived::NoRunner("does not start `test-runner`".to_string())); let said = refusal.to_string(); assert!(said.contains("parks on a console nothing is on"), "{said}"); let refusal = - derive("[boot]\nstart = [\"test-runner\"]\n[programs.logd]\n", &[], &[]).unwrap_err(); + derive("[boot]\nstart = [\"test-runner\"]\n[programs.logkeeper]\n", &[], &[]).unwrap_err(); assert!(matches!(refusal, Underived::NoRunner(_)), "{refusal:?}"); } } diff --git a/src/metalswap.rs b/src/metalswap.rs index 27c84069ac3..0e4c56ec13f 100644 --- a/src/metalswap.rs +++ b/src/metalswap.rs @@ -1,19 +1,19 @@ //! Replacing a running service's binary on a machine over its own cable, and -//! what the host heard of it: the ask over ssh, init's words over the record +//! what the host heard of it: the ask over ssh, the supervisor's words over the record //! stream, and the machine answering ssh again afterwards. //! //! One exchange for a QEMU guest and for the T14: the ask is an `exec` of -//! `/system/bin/swap` through the harness's russh client, and init's +//! `/system/bin/swap` through the harness's russh client, and the supervisor's //! verdict is read off the stream in [`toyos_swap::heard`]'s form. **The stream -//! is the one channel that outlives a swap of netd**: the ssh connection that -//! asked goes with the netd that carried it, and this side's connection to -//! `logd` goes with it too, with no FIN and no reset. So a swap of -//! [`toyos_logstream::CARRIER`] is let go only once `logd` has said it turns new -//! readers away until the next netd serves +//! is the one channel that outlives a swap of netstack**: the ssh connection that +//! asked goes with the netstack that carried it, and this side's connection to +//! `logkeeper` goes with it too, with no FIN and no reset. So a swap of +//! [`toyos_logstream::CARRIER`] is let go only once `logkeeper` has said it turns new +//! readers away until the next netstack serves //! ([`toyos_logstream::CARRIER_LEAVING`]), and this side then dials again -//! ([`Stream::redial`]) — every connection it makes before the old netd is gone +//! ([`Stream::redial`]) — every connection it makes before the old netstack is gone //! turned away, the first one admitted a connection through the new one — so -//! the verdict is whatever init said, as the machine's own log carries it. +//! the verdict is whatever the supervisor said, as the machine's own log carries it. use std::net::{SocketAddr, SocketAddrV4}; use std::path::Path; @@ -23,7 +23,7 @@ use toyos_swap::Word; use crate::metaltalk::{self, Exec, Ssh, Stream, SSH_PORT}; -/// How long the host keeps asking for the swap once the stream is open: sshd +/// How long the host keeps asking for the swap once the stream is open: sshserver /// may still be binding when a boot's stream opens. const ASK_WINDOW: Duration = Duration::from_secs(30); const RETRY: Duration = Duration::from_secs(1); @@ -32,17 +32,17 @@ const RETRY: Duration = Duration::from_secs(1); /// the answer is sent, over a stream the refusal left alone. const REFUSED_WORD: Duration = Duration::from_secs(10); -/// How long `logd`'s [`toyos_logstream::CARRIER_LEAVING`] has to reach this -/// side before the swap goes: `swap` hangs up on init this long after it -/// answered whether or not this side has closed its input, and the old netd is +/// How long `logkeeper`'s [`toyos_logstream::CARRIER_LEAVING`] has to reach this +/// side before the swap goes: `swap` hangs up on the supervisor this long after it +/// answered whether or not this side has closed its input, and the old netstack is /// stopped then. /// -/// **Not widened to cover a slow `logd` round, because nothing on this side -/// can.** The line reaches a reader in the round after the one `logd` was in -/// when it was said, and that round's flush may outlast `logd`'s own +/// **Not widened to cover a slow `logkeeper` round, because nothing on this side +/// can.** The line reaches a reader in the round after the one `logkeeper` was in +/// when it was said, and that round's flush may outlast `logkeeper`'s own /// `LOG_WRITE_BUDGET` on a slow volume; the swap goes on `swap`'s clock whatever /// this side waits for. A reader that dialled again without the line could be -/// admitted by the netd being stopped and lose its connection with no word, so +/// admitted by the netstack being stopped and lose its connection with no word, so /// a missing line is a red verdict rather than a longer wait. const CARRIER_WORD: Duration = Duration::from_millis(toyos_swap::ANSWER_MS); @@ -55,17 +55,17 @@ pub struct Swapped { pub digest: String, /// The machine's answer, or the client's last refusal to ask it. pub answer: Result, - /// Every word init said about this service on the stream after the ask. + /// Every word the supervisor said about this service on the stream after the ask. pub words: Vec<(Word, String)>, /// The service's own lines on the stream after the ask. pub said: Vec, - /// `echo` asked after init's verdict, through whatever carries the + /// `echo` asked after the supervisor's verdict, through whatever carries the /// network then. pub again: Result, /// Stream connections before the ask and when this ended. pub connections: (usize, usize), /// Dials the stream made from the ask on that ended with no line: each - /// redial `logd` or the machine turned away, refusals included. + /// redial `logkeeper` or the machine turned away, refusals included. pub turned_away: usize, /// From the ask to the answer, and to `echo`'s answer. pub answer_ms: u64, @@ -73,7 +73,7 @@ pub struct Swapped { } impl Swapped { - /// init's final word, if it said one. + /// The supervisor's final word, if it said one. pub fn outcome(&self) -> Option<&(Word, String)> { self.words.iter().rev().find(|(word, _)| word.is_final()) } @@ -89,38 +89,38 @@ pub struct Ask<'a> { } /// The manifest's name for the program whose lines judge a swap. -const INIT: &str = "init"; +const SUPERVISOR: &str = "supervisor"; -/// `line`'s text where it is `tag`'s own line: judged by the head `logd` +/// `line`'s text where it is `tag`'s own line: judged by the head `logkeeper` /// gives it (`toyos_logstream::program_line`), never by its words, so no other -/// program can say init's word for it. +/// program can say the supervisor's word for it. fn said_by<'a>(line: &'a str, tag: &str) -> Option<&'a str> { toyos_logstream::program_line(line).filter(|said| said.tag == tag).map(|said| said.text) } -/// init's word about `service` in `line`, where `line` is init's. -fn init_heard<'a>(line: &'a str, service: &str) -> Option<(Word, &'a str)> { - said_by(line, INIT).and_then(|text| toyos_swap::heard(text, service)) +/// The supervisor's word about `service` in `line`, where `line` is the supervisor's. +fn supervisor_heard<'a>(line: &'a str, service: &str) -> Option<(Word, &'a str)> { + said_by(line, SUPERVISOR).and_then(|text| toyos_swap::heard(text, service)) } /// Whether the wait for `service`'s outcome is over, reading `lines[mark..]`: -/// init's final word about it. A refusal `swap` made before init heard of the +/// The supervisor's final word about it. A refusal `swap` made before the supervisor heard of the /// ask is its answer on the channel (`unasked …`), and is never waited for here. fn settled(lines: &[String], mark: usize, service: &str) -> Option<()> { lines[mark.min(lines.len())..] .iter() - .any(|line| init_heard(line, service).is_some_and(|(word, _)| word.is_final())) + .any(|line| supervisor_heard(line, service).is_some_and(|(word, _)| word.is_final())) .then_some(()) } /// Ask the machine that opens `stream` to replace a service's binary, and -/// follow it to init's verdict and to ssh answering again. +/// follow it to the supervisor's verdict and to ssh answering again. /// -/// `ssh_at` is where sshd is reached, and `None` is the +/// `ssh_at` is where sshserver is reached, and `None` is the /// stream's peer's own port 22; QEMU's forward is the other case. /// /// `Err` is a boot that never opened the stream within `window`, a binary this -/// host cannot read, or a swap of the stream's own carrier whose `logd` never +/// host cannot read, or a swap of the stream's own carrier whose `logkeeper` never /// said it would turn readers away before `swap` let the swap go without /// this side. pub fn swap( @@ -166,12 +166,12 @@ pub fn swap( let heard = |lines: &[String]| -> Vec<(Word, String)> { lines[mark.min(lines.len())..] .iter() - .filter_map(|line| init_heard(line, service)) + .filter_map(|line| supervisor_heard(line, service)) .map(|(word, detail)| (word, detail.to_string())) .collect() }; - // A refusal leaves the service as it was, and init's word on it is on the - // stream at once; an accepted swap is followed to init's final word. + // A refusal leaves the service as it was, and the supervisor's word on it is on the + // stream at once; an accepted swap is followed to the supervisor's final word. let accepted = matches!(&answer, Ok(said) if said.starts_with("accepted ")); let until = match &answer { Ok(said) if said.starts_with("refused ") => Some(REFUSED_WORD), @@ -182,12 +182,12 @@ pub fn swap( let leaving = stream.wait_until(CARRIER_WORD, |lines| { lines[mark.min(lines.len())..] .iter() - .any(|line| said_by(line, toyos_logstream::LOGD) == Some(toyos_logstream::CARRIER_LEAVING)) + .any(|line| said_by(line, toyos_logstream::LOGKEEPER) == Some(toyos_logstream::CARRIER_LEAVING)) .then_some(()) }); if leaving.is_none() { return Err(format!( - "`logd` did not say it turns readers away within {} ms of the swap of {service} \ + "`logkeeper` did not say it turns readers away within {} ms of the swap of {service} \ being accepted, so `swap` let the swap go without this side, and the connection \ it carries may end with no word", CARRIER_WORD.as_millis() @@ -203,7 +203,7 @@ pub fn swap( let (left, seen, redialed) = (window.saturating_sub(began.elapsed()), stream.connections(), Instant::now()); stream.redial(left); if stream.wait_for_connection(seen, left).is_some() { - println!(" swap: `logd` admitted the stream again {} ms after the redial", redialed.elapsed().as_millis()); + println!(" swap: `logkeeper` admitted the stream again {} ms after the redial", redialed.elapsed().as_millis()); } } if let Some(until) = until { @@ -269,15 +269,15 @@ pub fn judge(heard: &Swapped, expect: Expect) -> Result, Vec Expect::InService => "accepted ", }; match &heard.answer { - // A refusal `swap` made itself, before init heard of the ask, is a - // refusal too, and the one init never speaks about. + // A refusal `swap` made itself, before the supervisor heard of the ask, is a + // refusal too, and the one the supervisor never speaks about. Ok(answer) if answer.starts_with(owed_prefix) || (expect == Expect::Refused && answer.starts_with("unasked ")) => { said.push(format!("the machine answered the swap of {service} {answer:?} in {} ms", heard.answer_ms)) } // The answer and the service carrying it can go together: what - // decides then is init's own word on the stream. + // decides then is the supervisor's own word on the stream. Ok(answer) if answer.starts_with("unanswered") && expect != Expect::Refused => { - said.push(format!("the swap of {service} was {answer:?}; init's words decide")) + said.push(format!("the swap of {service} was {answer:?}; the supervisor's words decide")) } other => bad.push(format!("the swap of {service} was answered {other:?}, where `{owed_prefix}…` is owed")), } @@ -285,17 +285,17 @@ pub fn judge(heard: &Swapped, expect: Expect) -> Result, Vec (Expect::InService, Some((Word::InService, detail))) => { let path = toyos_swap::installed_path(service, &toyos_swap::parse_hex(&heard.digest).unwrap_or_default()); if detail.starts_with(&path) { - said.push(format!("init: {service} is in service from {detail}")); + said.push(format!("supervisor: {service} is in service from {detail}")); } else { - bad.push(format!("init put {detail:?} in service, where {path} was sent")); + bad.push(format!("the supervisor put {detail:?} in service, where {path} was sent")); } } (Expect::Refused, _) if !word(Word::Stopping) => said.push(format!( - "init stopped nothing: {:?}", + "the supervisor stopped nothing: {:?}", heard.words.iter().map(|(w, d)| format!("{}: {d}", w.as_str())).collect::>() )), (_, outcome) => bad.push(format!( - "init's words on {service} were {:?} ending in {outcome:?}, where {expect:?} is owed \ + "the supervisor's words on {service} were {:?} ending in {outcome:?}, where {expect:?} is owed \ (the stream had {} connection(s) before the ask and {} after)", heard.words.iter().map(|(w, _)| w.as_str()).collect::>(), heard.connections.0, @@ -328,7 +328,7 @@ pub fn judge(heard: &Swapped, expect: Expect) -> Result, Vec mod tests { use super::*; - /// `text` as `logd` writes it under `tag`. + /// `text` as `logkeeper` writes it under `tag`. fn line(tag: &str, text: &str) -> String { let tag = toyos_logstream::Tag::new(tag).expect("a tag"); let stamp = "2026-09-24 22:01:37"; @@ -343,29 +343,29 @@ mod tests { }) } - /// init's words and `logd`'s carrier line count only under their own + /// The supervisor's words and `logkeeper`'s carrier line count only under their own /// programs' names: another program printing them settles nothing. #[test] fn a_judge_reads_the_speaker_from_the_head_and_never_the_words() { - let words = toyos_swap::said("netd", Word::InService, "/tmp/netd as pid 12"); - assert_eq!(settled(&[line("init", &words)], 0, "netd"), Some(())); - assert_eq!(settled(&[line("test-runner", &words), line("netd", &words)], 0, "netd"), None); - assert_eq!(settled(&[line("init", &words)], 1, "netd"), None, "before mark"); - assert_eq!(init_heard(&line("test-runner", &words), "netd"), None); - let leaving = line("logd", toyos_logstream::CARRIER_LEAVING); - assert_eq!(said_by(&leaving, toyos_logstream::LOGD), Some(toyos_logstream::CARRIER_LEAVING)); - assert_eq!(said_by(&line("netd", toyos_logstream::CARRIER_LEAVING), toyos_logstream::LOGD), None); + let words = toyos_swap::said("netstack", Word::InService, "/tmp/netstack as pid 12"); + assert_eq!(settled(&[line("supervisor", &words)], 0, "netstack"), Some(())); + assert_eq!(settled(&[line("test-runner", &words), line("netstack", &words)], 0, "netstack"), None); + assert_eq!(settled(&[line("supervisor", &words)], 1, "netstack"), None, "before mark"); + assert_eq!(supervisor_heard(&line("test-runner", &words), "netstack"), None); + let leaving = line("logkeeper", toyos_logstream::CARRIER_LEAVING); + assert_eq!(said_by(&leaving, toyos_logstream::LOGKEEPER), Some(toyos_logstream::CARRIER_LEAVING)); + assert_eq!(said_by(&line("netstack", toyos_logstream::CARRIER_LEAVING), toyos_logstream::LOGKEEPER), None); } fn heard(expect: Expect) -> Swapped { - let digest = toyos_swap::digest(b"netd"); - let path = toyos_swap::installed_path("netd", &digest); + let digest = toyos_swap::digest(b"netstack"); + let path = toyos_swap::installed_path("netstack", &digest); let (answer, words) = match expect { Expect::InService => ( format!("accepted {path}"), vec![ - (Word::Accepted, format!("{path} replaces /system/bin/netd (pid 7)")), - (Word::Stopping, "pid 7 (/system/bin/netd)".into()), + (Word::Accepted, format!("{path} replaces /system/bin/netstack (pid 7)")), + (Word::Stopping, "pid 7 (/system/bin/netstack)".into()), (Word::Started, format!("{path} as pid 12; in service if it runs 5000 ms")), (Word::InService, format!("{path} as pid 12")), ], @@ -376,11 +376,11 @@ mod tests { ), }; Swapped { - service: "netd".into(), + service: "netstack".into(), digest: toyos_swap::hex(&digest), answer: Ok(answer), words, - said: vec![line("netd", "netd: DHCP: lease 10.0.2.15/24 from 10.0.2.2, \"x\"")], + said: vec![line("netstack", "netstack: DHCP: lease 10.0.2.15/24 from 10.0.2.2, \"x\"")], again: Ok(Exec { stdout: metaltalk::owed(), status: Some(0) }), connections: (1, 2), turned_away: 3, @@ -390,7 +390,7 @@ mod tests { } /// Each expectation refuses the others' outcomes, and the machine not - /// answering afterwards is a finding whatever init said. + /// answering afterwards is a finding whatever the supervisor said. #[test] fn the_judge_holds_each_expectation_to_its_own_outcome() { for (got, want) in [ @@ -403,7 +403,7 @@ mod tests { silent.again = Err("connecting: refused".into()); assert!(judge(&silent, Expect::InService).is_err()); let mut elsewhere = heard(Expect::InService); - elsewhere.words.last_mut().unwrap().1 = "/tmp/swap/other/netd as pid 12".into(); + elsewhere.words.last_mut().unwrap().1 = "/tmp/swap/other/netstack as pid 12".into(); assert!(judge(&elsewhere, Expect::InService).is_err()); let mut spun = heard(Expect::InService); spun.turned_away = 10_000; diff --git a/src/metaltalk.rs b/src/metaltalk.rs index 0a5b6ed7c00..b5c31f06225 100644 --- a/src/metaltalk.rs +++ b/src/metaltalk.rs @@ -3,9 +3,9 @@ //! machine over ssh — a ping, one command whose answer is compared, and //! `reboot`, which is how the host hands the machine back. //! -//! **The machine is found by its name.** Its netd answers multicast DNS for +//! **The machine is found by its name.** Its netstack answers multicast DNS for //! `toyos-t14.local` once it holds a lease (`toyos_mdns`), so this host asks its -//! own resolver for that name and connects to `logd`'s port there +//! own resolver for that name and connects to `logkeeper`'s port there //! ([`toyos_logstream::PORT`]); nothing is baked into the image about this //! host, and nothing on this host listens. The ping and both ssh exchanges go //! to the address the name answered with. @@ -42,7 +42,7 @@ pub const PHRASE: &str = "the T14 answers over its own cable"; /// boot config endows with `power`. pub const REBOOT: &str = "reboot"; -/// The port sshd listens on, which is the protocol's own. +/// The port sshserver listens on, which is the protocol's own. pub const SSH_PORT: u16 = 22; /// How many echo requests the machine gets to answer one. @@ -96,10 +96,10 @@ pub enum Peer { /// boot is red. A redial has none ([`Stream::redial`]). const TURNED_AWAY_CEILING: usize = 64; -/// The log as this host reads it: this host dials `logd`'s port and reads until +/// The log as this host reads it: this host dials `logkeeper`'s port and reads until /// the connection ends. /// -/// **A connection is `logd`'s once it carries a line.** `logd` hands every +/// **A connection is `logkeeper`'s once it carries a line.** `logkeeper` hands every /// reader it admits the boot from its first line at once, so a connection that /// ends before a line is one it never admitted — and through QEMU's forward, /// which takes this host's connect before it has asked the guest, that is the @@ -126,11 +126,11 @@ struct Shared { #[derive(Default)] struct State { lines: Vec, - /// The latest connection `logd` admitted. + /// The latest connection `logkeeper` admitted. peer: Option, /// How many connections carried a line. admitted: usize, - /// How many dials ended with no line: a connection `logd` turned away, + /// How many dials ended with no line: a connection `logkeeper` turned away, /// one nothing on the machine's side took, or a connect that failed. turned_away: usize, /// The connection being read, kept so [`Stream::redial`] can end it. @@ -198,7 +198,7 @@ impl Stream { self.state().lines.clone() } - /// How many connections `logd` admitted. + /// How many connections `logkeeper` admitted. pub fn connections(&self) -> usize { self.state().admitted } @@ -225,7 +225,7 @@ impl Stream { self.state().end.clone() } - /// Why the latest dial ended with no connection `logd` admitted. + /// Why the latest dial ended with no connection `logkeeper` admitted. pub fn unopened(&self) -> Option { self.state().unopened.clone() } @@ -245,11 +245,11 @@ impl Stream { /// ([`Stream::unopened`]). /// /// **The admitted dial is the event, and `by` its only bound**: nothing the - /// machine sends says when `logd` admits a reader again, so how many dials + /// machine sends says when `logkeeper` admits a reader again, so how many dials /// that takes is the length of the machine's gap and no verdict — the /// recorded compromise `issues/diagnostics/a-swaps-redial-asks-again-with-no-event-to-wait-on.md`. /// - /// **For a connection this host knows is going**: a swap of the netd + /// **For a connection this host knows is going**: a swap of the netstack /// carrying it ends it with no FIN and no reset, so nothing but this host /// ever says it has ended. pub fn redial(&self, by: Duration) { @@ -319,7 +319,7 @@ impl Stream { /// until the stream is given up. fn serve(reach: &dyn Reach, peer: &Peer, shared: &Shared, mut out: std::fs::File, echo: bool, mut until: Instant) { // Whether a connection closed before a line is asked again: never on the - // first dial, where that close is `logd`'s answer, and always on a redial, + // first dial, where that close is `logkeeper`'s answer, and always on a redial, // which is made while the machine's network is coming back. let mut again = false; let mut last = String::from("never asked"); @@ -334,7 +334,7 @@ fn serve(reach: &dyn Reach, peer: &Peer, shared: &Shared, mut out: std::fs::File if echo { println!(" stream: reading {peer:?} at {:?}", conn.peer_addr().ok()); } - // A connection `logd` turned away on a redial: asked again at + // A connection `logkeeper` turned away on a redial: asked again at // once, the refusal being the event, and named by the dial // after it should the redial's bound end that one. if let Some(how) = read(conn, shared, &mut out, echo).filter(|_| again) { @@ -610,7 +610,7 @@ fn dns_name(bytes: &[u8], at: usize) -> Option<(String, usize)> { /// Read one connection's lines into the stream until it ends, and how it ended /// where it carried none. /// -/// **Every connection replays the boot from its first line** (`logd`'s +/// **Every connection replays the boot from its first line** (`logkeeper`'s /// `serve.rs`): the lines this reader already has are skipped rather than kept /// twice, and a line the connection ends inside is dropped rather than kept, so /// the same content lands whole on the next connection. @@ -688,7 +688,7 @@ pub struct End { pub how: String, } -/// What one exchange with the machine's sshd came back with. +/// What one exchange with the machine's sshserver came back with. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Exec { pub stdout: Vec, @@ -801,12 +801,12 @@ impl Ssh { /// Send `binary` as `service`'s replacement, naming `digest` for it — an /// `exec` of `/system/bin/swap` with the binary on its input — and answer - /// the machine's word: `accepted `, `refused ` (init's), + /// the machine's word: `accepted `, `refused ` (the supervisor's), /// `unasked ` (`swap`'s own), or `unanswered `. /// /// **An `accepted` is answered with the program's input still open**: - /// closing it is the go — `swap` hangs up on init once its input closes, - /// and init stops the old service then ([`toyos_swap::ANSWER_MS`] bounds + /// closing it is the go — `swap` hangs up on the supervisor once its input closes, + /// and the supervisor stops the old service then ([`toyos_swap::ANSWER_MS`] bounds /// the wait) — and it is [`Answered::go`]'s, so a caller whose own /// connection that service carries can see to it first. pub fn swap( @@ -912,12 +912,12 @@ pub fn owed() -> Vec { /// then ask it to reboot — whatever the first two said, because handing the /// machine back is owed either way. /// -/// `ssh_at` is where sshd is reached, and `None` is the peer's own port 22; +/// `ssh_at` is where sshserver is reached, and `None` is the peer's own port 22; /// QEMU's forward is the other case. `ping` is `false` where no ICMP can reach /// the machine at all, which is QEMU's user-mode network. /// /// **One ask of each**, each a wait on the machine's answer: a machine serving -/// its log holds a lease, and sshd binds its port before netd can have one. +/// its log holds a lease, and sshserver binds its port before netstack can have one. /// /// `Err` is only a stream that never opened. pub fn converse( @@ -973,7 +973,7 @@ pub fn converse( /// Ask for `reboot` through `fire` once the stream has carried this boot's /// `Boot: complete`, or once `by` has passed without it. `reboot` ends the -/// stream the judge reads that record off, and `logd` serves the boot from its +/// stream the judge reads that record off, and `logkeeper` serves the boot from its /// first line, so the backlog crosses at the network's pace and not the /// conversation's. fn hand_back(stream: &Stream, began: Instant, by: Duration, fire: impl FnOnce() -> T) -> T { @@ -1345,7 +1345,7 @@ mod tests { } /// **A first dial refused is asked again, counted, and ends at its - /// ceiling**: a machine still coming up refuses until `logd` listens, and + /// ceiling**: a machine still coming up refuses until `logkeeper` listens, and /// one that never does is named at the ceiling rather than waited on to /// the bound. The refusals are staged through [`Reach`]: a listener this /// process drops still takes connects while any child it is spawning holds @@ -1461,12 +1461,12 @@ mod tests { stream.wait_connected(Duration::from_secs(5)).expect("the peer"); assert!(stream.wait_for("Boot: complete", Duration::from_secs(5)), "the first line was not read"); assert!(!stream.wait_ended(Duration::ZERO), "a quiet peer was read as a closed one"); - writeln!(conn, "[kernel 1.217 cpu0] init: started logd").unwrap(); + writeln!(conn, "[kernel 1.217 cpu0] supervisor: started logkeeper").unwrap(); drop(conn); assert!(stream.wait_ended(Duration::from_secs(5))); assert_eq!( stream.lines(), - vec!["[kernel 1.216 cpu0] Boot: complete (1216ms)\n", "[kernel 1.217 cpu0] init: started logd\n"] + vec!["[kernel 1.216 cpu0] Boot: complete (1216ms)\n", "[kernel 1.217 cpu0] supervisor: started logkeeper\n"] ); } @@ -1524,9 +1524,9 @@ mod tests { /// **A redial ends the connection it replaces, asks again past every /// connection turned away before a line, and keeps each line once.** The - /// first connection is left open, as a swapped netd leaves it; the second - /// is closed before a byte, as `logd` turns a reader away; the third - /// replays the boot from its first line, as `logd` hands it to every + /// first connection is left open, as a swapped netstack leaves it; the second + /// is closed before a byte, as `logkeeper` turns a reader away; the third + /// replays the boot from its first line, as `logkeeper` hands it to every /// reader, and only its new line is kept. #[test] fn a_redial_asks_past_a_refusal_and_keeps_each_line_once() { @@ -1604,7 +1604,7 @@ mod tests { } /// `server` dropping the next `closed` connections before a byte, as - /// QEMU's forward does while `logd` turns readers away, and replaying the + /// QEMU's forward does while `logkeeper` turns readers away, and replaying the /// boot on the one after, with one line past it. fn close_then_replay(server: &TcpListener, closed: usize) { let server = server.try_clone().unwrap(); diff --git a/src/printer.rs b/src/printer.rs index 06e4e5441f9..01ef08dc9c9 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -1,6 +1,6 @@ //! The one printer: `eprintln!` in every target of this package is the macro //! below, so each statement the build system or the harness makes on stderr -//! opens with the UTC time of day it was made at — the clock `logd` stamps +//! opens with the UTC time of day it was made at — the clock `logkeeper` stamps //! `/log` with. A statement of several lines is stamped once, on its first. //! What a child process writes to the terminal, and what is written to //! stdout, pass through no printer and carry no stamp. diff --git a/src/qemu.rs b/src/qemu.rs index d51d077c4e9..100b509b05f 100644 --- a/src/qemu.rs +++ b/src/qemu.rs @@ -40,7 +40,7 @@ //! //! [`Options::dump_audio`] writes the device's output to //! `/tmp/toyos-audio.wav` (parse it to EOF — the RIFF sizes stay 0 unless the -//! guest shuts down cleanly). **Audio that sounds wrong is read from soundd's +//! guest shuts down cleanly). **Audio that sounds wrong is read from soundserver's //! and doom's printed numbers, never from the ear**: a starved synthesizer and //! a wrong playback clock are indistinguishable to a listener, and doom's //! real-time factor is what separates them — RTF near 1.0 with playback still diff --git a/src/sourcegate.rs b/src/sourcegate.rs index ea5d6724e32..568f537e36d 100644 --- a/src/sourcegate.rs +++ b/src/sourcegate.rs @@ -844,7 +844,7 @@ mod tests { let prefix = ["2a00", "1", "2", "300", "", ""].join(":"); let link_local = ["fe80", "", "1c2d", "3e4f", "5a6b", "7c8d"].join(":"); for (line, shape) in [ - (format!("netd: MAC {mac}"), MAC), + (format!("netstack: MAC {mac}"), MAC), (format!("MAC:{mac}: the lease went to it"), MAC), (format!("{mac}:eth0 took the lease"), MAC), (format!("? (10.0.2.2) at {} on en0", ["0", "11", "22", "3", "44", "55"].join(":")), MAC), @@ -864,7 +864,7 @@ mod tests { assert_eq!(shapes(&line), [shape], "{line}"); } for line in [ - "netd: MAC 52:54:00:12:34:56, ff:ff:ff:ff:ff:ff, 01:00:5e:00:00:fb, 33:33:00:00:00:01", + "netstack: MAC 52:54:00:12:34:56, ff:ff:ff:ff:ff:ff, 01:00:5e:00:00:fb, 33:33:00:00:00:01", "wire_mac 02:00:00:aa:bb:cc and the placeholder 00:00:00:00:00:01", "a longer run of octets 0a:1b:2c:3d:4e:5f:60:71, and 16:08:23 on 2026-09-08", "leased 10.0.2.15/24 from 10.0.2.2, 127.0.0.1, 169.254.1.1, 192.168.1.46, 172.16.0.1", diff --git a/system.toml b/system.toml index 6b90df230fc..7ad1913158f 100644 --- a/system.toml +++ b/system.toml @@ -1,8 +1,8 @@ -# sshd is deliberately not in `[boot] start`. It is built into the image and -# started by hand (`detach /system/bin/sshd`, so it outlives the shell) on a +# sshserver is deliberately not in `[boot] start`. It is built into the image and +# started by hand (`detach /system/bin/sshserver`, so it outlives the shell) on a # machine that wants remote access: it listens on every interface, so carrying # it in every boot is a listening port nobody asked for. -# `src/build.rs`'s `no_shipped_boot_config_starts_sshd` is the gate. +# `src/build.rs`'s `no_shipped_boot_config_starts_sshserver` is the gate. hosted-rustc = false @@ -13,7 +13,7 @@ hosted-rustc = false # day delete it. assets = ["assets"] -# What `/system/bin/init` starts at boot. Program keys, not paths, and the order means +# What `/system/bin/supervisor` starts at boot. Program keys, not paths, and the order means # nothing: every port exists before any server runs. [boot] # `filepicker` is a `serves` daemon like the three beside it: a machine-wide @@ -21,7 +21,7 @@ assets = ["assets"] # while the compositor had no way to ask for a program's *declared* authority — # the launcher gives it one, and starting a service from `[boot] start` is not # the thing that needed fixing. -start = ["logd", "blockd", "fsd", "compositor", "soundd", "netd", "filepicker"] +start = ["logkeeper", "diskserver", "fileserver", "compositor", "soundserver", "netstack", "filepicker"] # What every program launched out of `/apps` holds, whatever its own directory # says. A package is unpacked by `/system/bin/pkg` into a writable directory, so @@ -30,9 +30,9 @@ start = ["logd", "blockd", "fsd", "compositor", "soundd", "netd", "filepicker"] # `devices` and `syscap` have no spelling here, so nothing installed claims # hardware or enters the RT band. [apps] -receives = ["compositor", "soundd", "filepicker"] +receives = ["compositor", "soundserver", "filepicker"] -# `service = true` makes a row a system service: init starts it with `HOME` at +# `service = true` makes a row a system service: the supervisor starts it with `HOME` at # its own `/state/` and makes that directory first. Every other row runs # with the session user's home. [programs] @@ -45,10 +45,10 @@ toyos-ld = { path = "toyos-ld" } # **Every image that carries a `TOYOS-LOG` partition runs this**, and every # image does. The kernel keeps the record ring and the console and writes no -# file at all, so a boot config without `logd` is a boot whose `/log` is empty — -# `every_boot_config_runs_logd` is what refuses one. It claims no device, and +# file at all, so a boot config without `logkeeper` is a boot whose `/log` is empty — +# `every_boot_config_runs_logkeeper` is what refuses one. It claims no device, and # `log` is the port it answers `inspect` on. -[programs.logd] +[programs.logkeeper] service = true syscap = ["logread"] serves = ["log"] @@ -56,53 +56,53 @@ serves = ["log"] [programs.compositor] service = true serves = ["compositor"] -receives = ["soundd", "filepicker", "launcher"] +receives = ["soundserver", "filepicker", "launcher"] devices = ["framebuffer", "keyboard", "mouse"] -[programs.soundd] +[programs.soundserver] service = true -serves = ["soundd"] +serves = ["soundserver"] devices = ["hda-audio", "virtio-sound"] syscap = ["rt"] -# netd holds the NIC's PCI function and drives it: the virtqueues, the register +# netstack holds the NIC's PCI function and drives it: the virtqueues, the register # window and the interrupt are its own, and the kernel keeps only the claim. # Named by vendor and device rather than by slot, so one row finds the card # wherever firmware put it. -[programs.netd] +[programs.netstack] service = true -serves = ["netd"] +serves = ["netstack"] devices = ["pci:1af4:1041"] # `launcher` is how a login's program is started holding its own row: `update` # and `swap` below are two such programs. -[programs.sshd] +[programs.sshserver] service = true -receives = ["netd", "launcher"] +receives = ["netstack", "launcher"] # `swap` is the authority to replace a running service's binary; the build -# refuses it to any other program (`src/build.rs`). `ssh swap netd -# < netd` runs it for a login. +# refuses it to any other program (`src/build.rs`). `ssh swap netstack +# < netstack` runs it for a login. [programs.swap] receives = ["swap"] -# The idle slot: the slot table and the idle slot's two partitions, which init +# The idle slot: the slot table and the idle slot's two partitions, which the supervisor # claims against the ROOT the kernel holds. The build refuses it to any other # program; the owner's signature on the image is the authority to install it. # `ssh update < image` runs it for a login. [programs.update] slots = true -# A name's addresses, asked of netd's resolver: `netd` is the whole of what it +# A name's addresses, asked of netstack's resolver: `netstack` is the whole of what it # holds. [programs.host] -receives = ["netd"] +receives = ["netstack"] # The reader of every owner's `inspect` answer: a connector to each owner's # port, and `inventory` for the kernel's `dev.*`, are the whole of what it can # observe. [programs.inspect] -receives = ["netd", "soundd", "log", "compositor"] +receives = ["netstack", "soundserver", "log", "compositor"] syscap = ["inventory"] [programs.filepicker] @@ -118,7 +118,7 @@ receives = ["compositor", "launcher"] receives = ["surface", "launcher"] [programs.doom] -receives = ["compositor", "soundd"] +receives = ["compositor", "soundserver"] [programs.snake] receives = ["compositor", "filepicker"] @@ -138,17 +138,17 @@ receives = ["compositor", "filepicker"] receives = ["compositor", "filepicker"] # `power` is `/system/bin/shutdown`'s and `/system/bin/reboot`'s: the -# connector to init's port, which has `logd` make the log whole and then stops +# connector to the supervisor's port, which has `logkeeper` make the log whole and then stops # the machine with a `SysCap` no program in the image holds. `roster` is -# `/system/bin/ps`'s. Each of those is this binary under another name: init +# `/system/bin/ps`'s. Each of those is this binary under another name: the supervisor # resolves the symlink to this row, so the applets are endowed both and nothing # else in the image is. The row's granularity is the binary, so every other -# applet is endowed both too — the same shape as `soundd` reaching `ls`. +# applet is endowed both too — the same shape as `soundserver` reaching `ls`. # # `free` is the same syscall as `ps` and is named by neither: the machine header # is ambient and the process roster is not. [programs.toybox] -receives = ["compositor", "soundd", "surface", "power"] +receives = ["compositor", "soundserver", "surface", "power"] syscap = ["roster"] # Symlinks created on ROOT at build time. @@ -178,7 +178,7 @@ syscap = ["roster"] # The block service: the NVMe controller this machine's DATA is on, driven # from userland through its claim. Started again when it ends; the claim goes # back with the process and is minted again for the next. -[programs.blockd] +[programs.diskserver] service = true restart = true serves = ["block"] @@ -187,7 +187,7 @@ devices = ["pci:1b36:0010"] # The file servers: DATA, the log and the running slot's volume, one process # each, serving every program the directories of its role. Started again when # one ends, on the same ports. -[programs.fsd] +[programs.fileserver] restart = true roles = ["data", "log", "boot"] receives = ["block"] diff --git a/tests/CLAUDE.md b/tests/CLAUDE.md index b5c879df965..01bb2c654c3 100644 --- a/tests/CLAUDE.md +++ b/tests/CLAUDE.md @@ -7,7 +7,7 @@ The mechanics live where the work is: profiles and shapes in `tests/common/`, re - **A host that sleeps mid-run is reported, not measured** — a run whose wall clock jumped against the monotonic one reports `INVL` per test and exits 2. A wild outlier *not* marked that way is a real finding. - **A machine-wide kernel panic reds whichever test was running** — that red's name is the workload, never the cause. `QEMU died before ===READY=== (status 0)` is the same thing said silently: a guest that reset itself is a kernel death, and its evidence is the boot log. - **A machine-wide death during boot is reproduced by boots, not by suites** — parallel `bootable.img` guests, each waited on its completion marker and never on a fixed timer; the baseline is measured in the same session as the arm; a death counts whether or not a marker printed, so run guests with `-action reboot=shutdown -action shutdown=pause` and read a silent one's registers over QMP; a defect whose rate is set by interrupts per unit of guest work is measured on the *slowest* instrument — TCG can be the stronger oracle. -- **`/system/bin/init` speaks in every program's name before that program runs** — a predicate keyed on a `: ` prefix is satisfied by the wrong speaker; wait for the whole line, in the constant the assertion also reads. +- **`/system/bin/supervisor` speaks in every program's name before that program runs** — a predicate keyed on a `: ` prefix is satisfied by the wrong speaker; wait for the whole line, in the constant the assertion also reads. - **A guest binary cannot ask what a handle it does not hold does** — the probe ends its caller with exit 139, so it runs in a child, one fault per child. - **A boot's capture has two pieces** — `boot_log()` ends at the ready marker, `run_test`'s capture begins at `===TEST_START===`. - **A guest of an architecture the host is not runs under TCG** (`Arch::accel`) — TCG prices an uncontended atomic read-modify-write unlike hardware, and an x86-64 guest there boots `qemu64`, which has no PCID: every `INVPCID` path is dead, so a change gated on a CPUID feature is unverified by a green TCG suite. diff --git a/tests/checks.rs b/tests/checks.rs index 675103f936d..88cd2bdc418 100644 --- a/tests/checks.rs +++ b/tests/checks.rs @@ -874,7 +874,7 @@ mod checks { } } - /// One boot's readback, out of a `loader.log` and a `logd` text. + /// One boot's readback, out of a `loader.log` and a `logkeeper` text. fn readback(label: &str, loader: &str, log: &str) -> metal::Readback { let boot = "back_secs 50\nstick_secs 0\n"; metal::Readback::new(label, std::path::PathBuf::new(), loader.into(), log.into(), boot) diff --git a/tests/checks/audio.rs b/tests/checks/audio.rs index 18201a799d0..f1f504b1224 100644 --- a/tests/checks/audio.rs +++ b/tests/checks/audio.rs @@ -12,25 +12,25 @@ pub fn judges_verdict() -> Result<(), String> { }; let stats = |underruns: u32, clients: u32, deferred: u32| { format!( - "{{2.000 soundd}} soundd: wakes=9 completions=9 submitted=9 underruns={underruns} \ + "{{2.000 soundserver}} soundserver: wakes=9 completions=9 submitted=9 underruns={underruns} \ drains=0 max_wake_lat_us=9 max_batch=1 clients={clients} deferred={deferred} \ starve_max=0 worst_irq_late_us=0 worst_pickup_us=0 worst_empty=0 worst_batch=1 \ late_wakes=0\n" ) }; let spawn = |job: &str| format!("[kernel 1.000 cpu0] spawn: /system/bin/{job} pid=7\n"); - // One stream through soundd: `playing` is the stats line while it plays, + // One stream through soundserver: `playing` is the stats line while it plays, // and `ended` the flush once it has left. let session = |playing: String, how: &str, ended: String| { format!( - "{{1.000 soundd}} soundd: client 0 connected (id=1)\n{{1.000 soundd}} soundd: \ - resumed\n{playing}{{3.000 soundd}} soundd: client 1 removed ({how})\n{ended}\ - {{3.000 soundd}} soundd: suspended\n" + "{{1.000 soundserver}} soundserver: client 0 connected (id=1)\n{{1.000 soundserver}} soundserver: \ + resumed\n{playing}{{3.000 soundserver}} soundserver: client 1 removed ({how})\n{ended}\ + {{3.000 soundserver}} soundserver: suspended\n" ) }; let next = spawn("test_rs_next"); - let configured = "{0.500 soundd} soundd: hda path configured in 3 ms\n"; + let configured = "{0.500 soundserver} soundserver: hda path configured in 3 ms\n"; let tone = |ended: String| { format!("{configured}{}{}", spawn("test_rs_audio_tone"), session(stats(0, 1, 0), "closed", ended)) }; @@ -45,19 +45,19 @@ pub fn judges_verdict() -> Result<(), String> { judged( "a tone on the null sink", tone_on_metal, - &format!("{}{{0.600 soundd}} {NULL_SINK}\n{next}", tone(stats(0, 0, 0))), + &format!("{}{{0.600 soundserver}} {NULL_SINK}\n{next}", tone(stats(0, 0, 0))), false, )?; - // The next job's stream connected before soundd let the tone's go, so the + // The next job's stream connected before soundserver let the tone's go, so the // tone's last window is both streams' whatever it counted. judged( "a tone another job's stream joined", tone_on_metal, &format!( - "{configured}{}{{1.000 soundd}} soundd: client 0 connected (id=1)\n{}{next}\ - {{3.000 soundd}} soundd: client 1 connected (id=2)\n\ - {{3.000 soundd}} soundd: client 1 removed (closed)\n{}\ - {{4.000 soundd}} soundd: client 2 removed (closed)\n{}", + "{configured}{}{{1.000 soundserver}} soundserver: client 0 connected (id=1)\n{}{next}\ + {{3.000 soundserver}} soundserver: client 1 connected (id=2)\n\ + {{3.000 soundserver}} soundserver: client 1 removed (closed)\n{}\ + {{4.000 soundserver}} soundserver: client 2 removed (closed)\n{}", spawn("test_rs_audio_tone"), stats(0, 1, 0), stats(0, 1, 0), @@ -69,7 +69,7 @@ pub fn judges_verdict() -> Result<(), String> { "a tone whose window ended before its stream connected", tone_on_metal, &format!( - "{configured}{}{{0.900 soundd}} soundd: client 0 removed (closed)\n{}{}{next}", + "{configured}{}{{0.900 soundserver}} soundserver: client 0 removed (closed)\n{}{}{next}", spawn("test_rs_audio_tone"), stats(0, 0, 0), session(stats(0, 1, 0), "closed", stats(0, 0, 0)) @@ -79,13 +79,13 @@ pub fn judges_verdict() -> Result<(), String> { // Another job's stream, held since before the spawn, is still held when the // tone's connects: one connect in the window, and two removals. judged( - "a tone beside a stream soundd held at its spawn", + "a tone beside a stream soundserver held at its spawn", tone_on_metal, &format!( - "{configured}{{0.900 soundd}} soundd: client 0 connected (id=0)\n{}\ - {{1.000 soundd}} soundd: client 1 connected (id=1)\n{}\ - {{2.500 soundd}} soundd: client 0 removed (closed)\n\ - {{3.000 soundd}} soundd: client 1 removed (closed)\n{}{next}", + "{configured}{{0.900 soundserver}} soundserver: client 0 connected (id=0)\n{}\ + {{1.000 soundserver}} soundserver: client 1 connected (id=1)\n{}\ + {{2.500 soundserver}} soundserver: client 0 removed (closed)\n\ + {{3.000 soundserver}} soundserver: client 1 removed (closed)\n{}{next}", spawn("test_rs_audio_tone"), stats(0, 2, 0), stats(0, 0, 0), @@ -103,21 +103,21 @@ pub fn judges_verdict() -> Result<(), String> { let second = session(stats(1, 1, 0), "closed", stats(0, 0, 0)); judged("the stalled client", client_stall_on_metal, &stall(second.clone(), &next), true)?; judged( - "a stalled client whose second stream never resumed soundd", + "a stalled client whose second stream never resumed soundserver", client_stall_on_metal, - &stall(second.replace("soundd: resumed\n", "soundd: client 0 streaming\n"), &next), + &stall(second.replace("soundserver: resumed\n", "soundserver: client 0 streaming\n"), &next), false, )?; judged( - "a stalled client soundd filled no period for", + "a stalled client soundserver filled no period for", client_stall_on_metal, &stall(second.clone(), &next).replace("underruns=3", "underruns=0").replace("underruns=1", "underruns=0"), false, )?; - // The next job spawned ahead of soundd's last word on the second stream. - let (playing, tail) = second.split_at(second.find("{3.000 soundd} soundd: client 1 removed").expect("staged")); + // The next job spawned ahead of soundserver's last word on the second stream. + let (playing, tail) = second.split_at(second.find("{3.000 soundserver} soundserver: client 1 removed").expect("staged")); judged( - "a stalled client soundd deferred for after the next job began", + "a stalled client soundserver deferred for after the next job began", client_stall_on_metal, &stall(format!("{playing}{next}{}", tail.replace("deferred=0", "deferred=1")), ""), false, @@ -125,16 +125,16 @@ pub fn judges_verdict() -> Result<(), String> { judged( "a stalled client over a repeated completion", client_stall_on_metal, - &stall(second.clone(), &format!("{{2.500 soundd}} soundd: repeated completion for free buffer\n{next}")), + &stall(second.clone(), &format!("{{2.500 soundserver}} soundserver: repeated completion for free buffer\n{next}")), false, )?; judged("the T14's stalled client", client_stall_on_metal, T14_STALL, true)?; judged( - "the T14's stalled client, its second stream opened on a running soundd", + "the T14's stalled client, its second stream opened on a running soundserver", client_stall_on_metal, &T14_STALL - .replace("{2026-10-03 07:05:06 7.865 soundd} soundd: suspended\n", "") - .replace("{2026-10-03 07:05:07 8.143 soundd} soundd: resumed\n", ""), + .replace("{2026-10-03 07:05:06 7.865 soundserver} soundserver: suspended\n", "") + .replace("{2026-10-03 07:05:07 8.143 soundserver} soundserver: resumed\n", ""), false, )?; @@ -147,21 +147,21 @@ pub fn judges_verdict() -> Result<(), String> { ) }; judged("two departures", departures_on_metal, &departures("signal pipe gone"), true)?; - judged("a departure soundd did not establish", departures_on_metal, &departures("died"), false)?; + judged("a departure soundserver did not establish", departures_on_metal, &departures("died"), false)?; judged( - "a death soundd claimed beside a departure it established", + "a death soundserver claimed beside a departure it established", departures_on_metal, &departures("closed").replacen( - "{3.000 soundd} soundd: client 1 removed", - "{3.000 soundd} soundd: client 1 died\n{3.000 soundd} soundd: client 1 removed", + "{3.000 soundserver} soundserver: client 1 removed", + "{3.000 soundserver} soundserver: client 1 died\n{3.000 soundserver} soundserver: client 1 removed", 1, ), false, )?; judged( - "a departure soundd never reported", + "a departure soundserver never reported", departures_on_metal, - &departures("closed").replacen("{3.000 soundd} soundd: client 1 removed (closed)\n", "", 1), + &departures("closed").replacen("{3.000 soundserver} soundserver: client 1 removed (closed)\n", "", 1), false, )?; judged( @@ -176,11 +176,11 @@ pub fn judges_verdict() -> Result<(), String> { )?; let idle = |said: &str| format!("{}{said}{next}", spawn("test_rs_audio_idle_suspend")); - judged("an idle soundd", idle_suspend_on_metal, &idle("{1.000 soundd} soundd: suspended\n"), true)?; + judged("an idle soundserver", idle_suspend_on_metal, &idle("{1.000 soundserver} soundserver: suspended\n"), true)?; judged( - "an idle soundd that started the device", + "an idle soundserver that started the device", idle_suspend_on_metal, - &idle(&format!("{{1.000 soundd}} {DEVICE_STARTED}\n")), + &idle(&format!("{{1.000 soundserver}} {DEVICE_STARTED}\n")), false, )?; @@ -188,14 +188,14 @@ pub fn judges_verdict() -> Result<(), String> { // both others in `/log`, and five counted unwritten. let stalled = |held: u32, unwritten: u32, refusals: usize| { format!( - "{{1.000 test_rs_soundd_log_stall}} flooded soundd with 10 refusals\n\ - {{1.000 test_rs_soundd_log_stall}} soundd refused 1 probe\n\ - {}{{1.100 soundd}} soundd: protocol violation (msg 7)\n\ - {{1.200 soundd}} soundd: opening stream: 48000 Hz\n\ - {{2.000 logd}} logd: reading soundd again, as `--stall-until` asked, with {held} of \ + "{{1.000 test_rs_soundserver_log_stall}} flooded soundserver with 10 refusals\n\ + {{1.000 test_rs_soundserver_log_stall}} soundserver refused 1 probe\n\ + {}{{1.100 soundserver}} soundserver: protocol violation (msg 7)\n\ + {{1.200 soundserver}} soundserver: opening stream: 48000 Hz\n\ + {{2.000 logkeeper}} logkeeper: reading soundserver again, as `--stall-until` asked, with {held} of \ its ring's 64 slots waiting\n\ - {{2.100 logd}} logd: {unwritten} record(s) of soundd's found its ring full\n", - "{1.050 soundd} soundd: refusing connection, too many\n".repeat(refusals) + {{2.100 logkeeper}} logkeeper: {unwritten} record(s) of soundserver's found its ring full\n", + "{1.050 soundserver} soundserver: refusing connection, too many\n".repeat(refusals) ) }; judged("the stalled log", log_stall_on_metal, &stalled(64, 5, 6), true)?; @@ -207,26 +207,26 @@ pub fn judges_verdict() -> Result<(), String> { /// The T14's `testcases` boot, verbatim: the tone's last records, and the /// stalled client's from its spawn to its exit. Its first stream opens 3 ms -/// after the tone's left, on a soundd that has not suspended. -const T14_STALL: &str = r"{2026-10-03 07:05:04 5.681 soundd} soundd: client 0 removed (closed) -{2026-10-03 07:05:04 5.681 soundd} soundd: wakes=573 completions=415 submitted=415 underruns=0 drains=0 max_wake_lat_us=2307 max_batch=2 clients=0 deferred=0 starve_max=0 worst_irq_late_us=2288 worst_pickup_us=18 worst_empty=0 worst_batch=2 late_wakes=0 +/// after the tone's left, on a soundserver that has not suspended. +const T14_STALL: &str = r"{2026-10-03 07:05:04 5.681 soundserver} soundserver: client 0 removed (closed) +{2026-10-03 07:05:04 5.681 soundserver} soundserver: wakes=573 completions=415 submitted=415 underruns=0 drains=0 max_wake_lat_us=2307 max_batch=2 clients=0 deferred=0 starve_max=0 worst_irq_late_us=2288 worst_pickup_us=18 worst_empty=0 worst_batch=2 late_wakes=0 [2026-10-03 07:05:04 5.682 cpu4] exit: test_rs_audio_tone pid=11 code=0 cpu=2ms [2026-10-03 07:05:04 5.683 cpu7] spawn: /system/bin/test_rs_hda_client_stall pid=12 tid=0 dst=6 base=0x10000000000 entry=0x1000003df40 root=0x83d6000 symbols=2048KiB (layout=0ms relocs=0ms deps=0ms tls=0ms total=1ms) -{2026-10-03 07:05:04 5.684 tid=1 soundd} soundd: opening stream: 44100Hz 2ch fmt=0 -{2026-10-03 07:05:04 5.684 soundd} soundd: client 0 connected (id=1) -{2026-10-03 07:05:06 7.685 soundd} soundd: wakes=842 completions=690 submitted=690 underruns=104 drains=0 max_wake_lat_us=1746 max_batch=2 clients=1 deferred=0 starve_max=13 worst_irq_late_us=1724 worst_pickup_us=22 worst_empty=0 worst_batch=2 late_wakes=0 -{2026-10-03 07:05:06 7.842 soundd} soundd: client 1 removed (closed) -{2026-10-03 07:05:06 7.842 soundd} soundd: wakes=85 completions=54 submitted=54 underruns=0 drains=0 max_wake_lat_us=70 max_batch=1 clients=0 deferred=0 starve_max=0 worst_irq_late_us=17 worst_pickup_us=53 worst_empty=1 worst_batch=1 late_wakes=0 +{2026-10-03 07:05:04 5.684 tid=1 soundserver} soundserver: opening stream: 44100Hz 2ch fmt=0 +{2026-10-03 07:05:04 5.684 soundserver} soundserver: client 0 connected (id=1) +{2026-10-03 07:05:06 7.685 soundserver} soundserver: wakes=842 completions=690 submitted=690 underruns=104 drains=0 max_wake_lat_us=1746 max_batch=2 clients=1 deferred=0 starve_max=13 worst_irq_late_us=1724 worst_pickup_us=22 worst_empty=0 worst_batch=2 late_wakes=0 +{2026-10-03 07:05:06 7.842 soundserver} soundserver: client 1 removed (closed) +{2026-10-03 07:05:06 7.842 soundserver} soundserver: wakes=85 completions=54 submitted=54 underruns=0 drains=0 max_wake_lat_us=70 max_batch=1 clients=0 deferred=0 starve_max=0 worst_irq_late_us=17 worst_pickup_us=53 worst_empty=1 worst_batch=1 late_wakes=0 [2026-10-03 07:05:06 7.842 cpu7 tid=1] exit: test_rs_hda_client_stall tid=1 code=0 cpu=15ms -{2026-10-03 07:05:06 7.865 soundd} soundd: suspended -{2026-10-03 07:05:07 8.142 tid=1 soundd} soundd: opening stream: 44100Hz 2ch fmt=0 -{2026-10-03 07:05:07 8.142 soundd} soundd: client 0 connected (id=2) -{2026-10-03 07:05:07 8.143 soundd} soundd: resumed -{2026-10-03 07:05:08 9.051 soundd} soundd: client 2 removed (closed) -{2026-10-03 07:05:08 9.051 soundd} soundd: wakes=425 completions=313 submitted=321 underruns=26 drains=0 max_wake_lat_us=88 max_batch=1 clients=0 deferred=0 starve_max=13 worst_irq_late_us=53 worst_pickup_us=34 worst_empty=1 worst_batch=1 late_wakes=0 +{2026-10-03 07:05:06 7.865 soundserver} soundserver: suspended +{2026-10-03 07:05:07 8.142 tid=1 soundserver} soundserver: opening stream: 44100Hz 2ch fmt=0 +{2026-10-03 07:05:07 8.142 soundserver} soundserver: client 0 connected (id=2) +{2026-10-03 07:05:07 8.143 soundserver} soundserver: resumed +{2026-10-03 07:05:08 9.051 soundserver} soundserver: client 2 removed (closed) +{2026-10-03 07:05:08 9.051 soundserver} soundserver: wakes=425 completions=313 submitted=321 underruns=26 drains=0 max_wake_lat_us=88 max_batch=1 clients=0 deferred=0 starve_max=13 worst_irq_late_us=53 worst_pickup_us=34 worst_empty=1 worst_batch=1 late_wakes=0 [2026-10-03 07:05:08 9.051 cpu0 tid=2] exit: test_rs_hda_client_stall tid=2 code=0 cpu=3ms -{2026-10-03 07:05:08 9.079 soundd} soundd: suspended -{2026-10-03 07:05:08 9.079 soundd} soundd: idle wake 1 (1 records) -{2026-10-03 07:05:08 9.351 pid=12 test-runner} stalled 8 then 2 times, soundd survived +{2026-10-03 07:05:08 9.079 soundserver} soundserver: suspended +{2026-10-03 07:05:08 9.079 soundserver} soundserver: idle wake 1 (1 records) +{2026-10-03 07:05:08 9.351 pid=12 test-runner} stalled 8 then 2 times, soundserver survived [2026-10-03 07:05:08 9.352 cpu6] exit: test_rs_hda_client_stall pid=12 code=0 cpu=2ms "; diff --git a/tests/checks/lan.rs b/tests/checks/lan.rs index c82439df912..80ada23391f 100644 --- a/tests/checks/lan.rs +++ b/tests/checks/lan.rs @@ -4,16 +4,16 @@ use super::*; use toyos_build::metal::{READBACK_BOOT, READBACK_STREAM, READBACK_TALK}; -/// The T14's `lantalkcase` boot: the card's hand-over, what netd said of its -/// MAC, its link and its lease, and init's stop. The MAC and the two resolvers +/// The T14's `lantalkcase` boot: the card's hand-over, what netstack said of its +/// MAC, its link and its lease, and the supervisor's stop. The MAC and the two resolvers /// are stand-ins that name nobody; every other byte is the machine's. const LOG: &str = r"[2026-10-03 10:20:01 1.192 cpu0] pcidev: PCI 00:1f.6 [8086:15fc] handed over on slot 0, vector 0x28 -{2026-10-03 10:20:05 5.727 netd} netd: MAC 02:00:00:00:00:01 +{2026-10-03 10:20:05 5.727 netstack} netstack: MAC 02:00:00:00:00:01 [2026-10-03 10:20:08 8.499 cpu4] pcidev: slot 0 took its first message on vector 0x28 -{2026-10-03 10:20:08 8.499 netd} netd: I219: link up at 1000 Mb/s full duplex, 2772 ms after the driver came up -{2026-10-03 10:20:19 19.053 netd} netd: DHCP: lease 192.168.1.48/24 from 192.168.1.1, gateway 192.168.1.1, dns [192.0.2.53 198.51.100.53], 13326 ms after netd came up -{2026-10-03 10:20:19 19.053 netd} netd: ready, at most 103 piped connections (4 MiB each of 16022 MiB total) -{2026-10-03 10:20:20 20.249 init} init: power: the machine stops, and logd makes the log whole first (Reboot) +{2026-10-03 10:20:08 8.499 netstack} netstack: I219: link up at 1000 Mb/s full duplex, 2772 ms after the driver came up +{2026-10-03 10:20:19 19.053 netstack} netstack: DHCP: lease 192.168.1.48/24 from 192.168.1.1, gateway 192.168.1.1, dns [192.0.2.53 198.51.100.53], 13326 ms after netstack came up +{2026-10-03 10:20:19 19.053 netstack} netstack: ready, at most 103 piped connections (4 MiB each of 16022 MiB total) +{2026-10-03 10:20:20 20.249 supervisor} supervisor: power: the machine stops, and logkeeper makes the log whole first (Reboot) "; /// That boot's `boot.txt`, under the same stand-in. @@ -37,8 +37,8 @@ fn judged(log: &str, boot: &str) -> Result<(), String> { } /// The lease judged is the one this boot took: the T14's boot passes on the -/// address it answered the host at, and reds where netd's record names another -/// address, where netd read another MAC than Ubuntu did, and with no lease. +/// address it answered the host at, and reds where netstack's record names another +/// address, where netstack read another MAC than Ubuntu did, and with no lease. pub fn the_lease_judged_is_this_boots_own() { assert_eq!(judged(LOG, BOOT), Ok(())); let refused = |what: &str, log: &str, boot: &str, says: &str| { @@ -55,7 +55,7 @@ pub fn the_lease_judged_is_this_boots_own() { "a MAC that is not the one Ubuntu read", LOG, &BOOT.replace("wire_mac 02:00:00:00:00:01", "wire_mac 02:00:00:00:00:02"), - "no \"netd: MAC \" record names the MAC the operating system before this boot read", + "no \"netstack: MAC \" record names the MAC the operating system before this boot read", ); let unleased: String = LOG.lines().filter(|l| !l.contains("DHCP: lease")).map(|l| format!("{l}\n")).collect(); diff --git a/tests/checks/qemu.rs b/tests/checks/qemu.rs index 760b4c6306e..c9b8a0ed406 100644 --- a/tests/checks/qemu.rs +++ b/tests/checks/qemu.rs @@ -93,7 +93,7 @@ pub fn ceiling_self_check() -> Result<(), String> { // read loop asks, so the case is staged where the loop reads it: the // same words from a program classify as nobody's business, and a wait // with no kernel death in it runs on. - const USER: &str = "thread 'main' (1) panicked at sshd/src/main.rs:359:23:"; + const USER: &str = "thread 'main' (1) panicked at sshserver/src/main.rs:359:23:"; if super::serial::died(USER) == Some(super::serial::Died::Kernel) { return Err(format!("a program's own panic reads as the kernel's: {USER:?}")); } diff --git a/tests/checks/serial.rs b/tests/checks/serial.rs index 305a1b71a66..3185b69a0e3 100644 --- a/tests/checks/serial.rs +++ b/tests/checks/serial.rs @@ -29,10 +29,10 @@ pub fn self_check() -> Result<(), String> { "test capture", "[2026-09-29 11:11:20 0.000 cpu0 boot] panic console: armed 1920x1080 stride=1920 \ format=1 at 0x4000000000, write-combining\n\ - {2026-09-29 11:11:21 1.170 init} init: started logd\n", + {2026-09-29 11:11:21 1.170 supervisor} supervisor: started logkeeper\n", ); let readback_mute = - Serial::named("test capture", "{2026-09-29 11:11:21 1.170 init} init: started logd\n"); + Serial::named("test capture", "{2026-09-29 11:11:21 1.170 supervisor} supervisor: started logkeeper\n"); let panicking = Serial::named( "test capture", "[kernel 0.001 cpu0] NVMe: found\n[kernel 0.002 cpu0] PANIC: nope\n", @@ -142,7 +142,7 @@ pub fn self_check() -> Result<(), String> { // the same words, once from the kernel and once from somebody else. const KERNEL_PANIC_LINE: &str = "[kernel 1.450 cpu3] PANIC: panicked at kernel/src/sched/reserve.rs:812:9:"; - const USER_PANIC_LINE: &str = "thread 'main' (1) panicked at sshd/src/main.rs:359:23:"; + const USER_PANIC_LINE: &str = "thread 'main' (1) panicked at sshserver/src/main.rs:359:23:"; let whose: &[(&str, Option)] = &[ // The kernel, about itself. (KERNEL_PANIC_LINE, Some(Died::Kernel)), @@ -190,7 +190,7 @@ pub fn self_check() -> Result<(), String> { ("PANIC: printed by a program that felt like printing it", Some(Died::Panicked)), // A `/log` readback's heads: the kernel's panic, and a program's. ("[2026-09-29 11:11:22 2.000 cpu1] PANIC: nope", Some(Died::Kernel)), - ("{2026-09-29 11:11:22 2.000 init} PANIC: printed by init", Some(Died::Panicked)), + ("{2026-09-29 11:11:22 2.000 supervisor} PANIC: printed by the supervisor", Some(Died::Panicked)), // Nothing died. ("[kernel 0.377 cpu0] NVMe: found", None), ("hello from userland", None), @@ -239,7 +239,7 @@ pub fn self_check() -> Result<(), String> { [kernel 6.204 cpu1] cr2=0xffff800002672ff8 (address that caused the fault chain)\n\ [kernel 6.204 cpu1] rip=0xffffffff80121a40 rsp=0xffff800002673000 rbp=0x0\n\ [kernel 6.204 cpu1] Kernel backtrace:\n\ - soundd: suspended\n\ + soundserver: suspended\n\ [kernel 6.205 cpu1] Found interrupt frame at stack offset +0x18:\n" ); let Some(report) = death_report(&staged_df) else { @@ -266,7 +266,7 @@ pub fn self_check() -> Result<(), String> { // A line another process wrote *after* the header stays: the console is not // line-atomic and a report with holes cut in it is worse than one with a // daemon's line in the middle. - if !report.contains("soundd: suspended") { + if !report.contains("soundserver: suspended") { return Err(format!("the report drops the lines it did not recognise:\n{report}")); } // The other direction, and the one that keeps this out of everybody's diff --git a/tests/common/audio.rs b/tests/common/audio.rs index b065cf7dd74..46a61b33721 100644 --- a/tests/common/audio.rs +++ b/tests/common/audio.rs @@ -1,17 +1,17 @@ -//! soundd judged off the log the T14's stick came back with. Audio is judged on +//! soundserver judged off the log the T14's stick came back with. Audio is judged on //! metal and nowhere else: no QEMU guest test plays it. use super::serial::Serial; /// The text of `log` from the kernel's record of `job`'s spawn to the end of -/// what soundd said about the `sessions` streams it played, one after another. +/// what soundserver said about the `sessions` streams it played, one after another. /// -/// A session ends at soundd's flush on its last client leaving — the stats line -/// that carries `clients=0`, which soundd writes after the removal — and not at +/// A session ends at soundserver's flush on its last client leaving — the stats line +/// that carries `clients=0`, which soundserver writes after the removal — and not at /// the next job's spawn, which can land before it. A job that plays nothing /// (`sessions` of 0) ends at the next test binary's spawn. /// -/// Sessions are refused unless each is one stream: soundd counts one window +/// Sessions are refused unless each is one stream: soundserver counts one window /// across every client it holds, so a session another job's stream shared has /// no count that is the job's alone. fn job_window<'a>(log: &'a str, job: &str, sessions: usize) -> Result<&'a str, String> { @@ -25,11 +25,11 @@ fn job_window<'a>(log: &'a str, job: &str, sessions: usize) -> Result<&'a str, S for session in 1..=sessions { let flushed = rest[end..] .match_indices(SESSION_ENDED) - .find(|&(line_at, _)| is_soundd_stats(&rest[end..], line_at)) + .find(|&(line_at, _)| is_soundserver_stats(&rest[end..], line_at)) .map(|(line_at, _)| end + line_at) .ok_or_else(|| { format!( - "soundd never said session {session} of {job}'s {sessions} ended (a stats \ + "soundserver never said session {session} of {job}'s {sessions} ended (a stats \ line with `{}`):\n{rest}", SESSION_ENDED.trim() ) @@ -38,78 +38,78 @@ fn job_window<'a>(log: &'a str, job: &str, sessions: usize) -> Result<&'a str, S } let window = &rest[..end]; let said = |what: &str| { - window.lines().filter(|l| l.contains("soundd: client ") && l.contains(what)).count() + window.lines().filter(|l| l.contains("soundserver: client ") && l.contains(what)).count() }; - // A removal counts too: a stream soundd held before the spawn connected + // A removal counts too: a stream soundserver held before the spawn connected // outside the window and leaves inside it. let (streams, removed) = (said(" connected (id="), said(" removed (")); if streams != sessions || removed != sessions { return Err(format!( - "soundd connected {streams} and removed {removed} stream(s) in {job}'s {sessions} \ - session(s): another job's stream shared soundd with {job}'s, and no count in the \ + "soundserver connected {streams} and removed {removed} stream(s) in {job}'s {sessions} \ + session(s): another job's stream shared soundserver with {job}'s, and no count in the \ window is {job}'s alone:\n{window}" )); } Ok(window) } -/// What soundd's flush on its last client leaving carries, and no other stats +/// What soundserver's flush on its last client leaving carries, and no other stats /// line does. const SESSION_ENDED: &str = " clients=0 "; -/// Whether the match at `at` in `text` is on one of soundd's stats lines. -fn is_soundd_stats(text: &str, at: usize) -> bool { +/// Whether the match at `at` in `text` is on one of soundserver's stats lines. +fn is_soundserver_stats(text: &str, at: usize) -> bool { let line_start = text[..at].rfind('\n').map_or(0, |nl| nl + 1); - text[line_start..at].contains("soundd: wakes=") + text[line_start..at].contains("soundserver: wakes=") } -/// The tone client played to its end through the HDA controller soundd drives -/// itself, soundd never fell back to the null sink, and no period of it went +/// The tone client played to its end through the HDA controller soundserver drives +/// itself, soundserver never fell back to the null sink, and no period of it went /// unfilled. pub fn tone_on_metal(log: &Serial) -> Result<(), String> { - log.must_say("soundd: hda path configured in")?; + log.must_say("soundserver: hda path configured in")?; log.must_not_say(NULL_SINK)?; let window = job_window(log.text(), "test_rs_audio_tone", 1)?; let underruns = sum_field(window, "underruns"); if underruns != 0 { return Err(format!( - "soundd filled {underruns} period(s) the tone client had not covered, on a client \ + "soundserver filled {underruns} period(s) the tone client had not covered, on a client \ that keeps its ring full:\n{window}" )); } Ok(()) } -/// soundd's own word for the sink it took when the machine has none. -pub const NULL_SINK: &str = "soundd: no audio device, presenting a null sink"; +/// soundserver's own word for the sink it took when the machine has none. +pub const NULL_SINK: &str = "soundserver: no audio device, presenting a null sink"; -/// soundd with no client costs no CPU, and the device is not what is running: -/// in a window no client connects in, soundd never started the stream. A zero -/// CPU delta is the signature of a suspended soundd and equally of one wedged +/// soundserver with no client costs no CPU, and the device is not what is running: +/// in a window no client connects in, soundserver never started the stream. A zero +/// CPU delta is the signature of a suspended soundserver and equally of one wedged /// with the device running; the start line tells them apart. pub fn idle_suspend_on_metal(log: &Serial) -> Result<(), String> { let window = job_window(log.text(), "test_rs_audio_idle_suspend", 0)?; if window.contains(DEVICE_STARTED) { return Err(format!( - "`{DEVICE_STARTED}` with no client connected — soundd's zero CPU is the device left \ + "`{DEVICE_STARTED}` with no client connected — soundserver's zero CPU is the device left \ running, not a suspend:\n{window}" )); } Ok(()) } -/// What soundd says as it starts the stream, before the first submit. -pub(crate) const DEVICE_STARTED: &str = "soundd: resumed"; +/// What soundserver says as it starts the stream, before the first submit. +pub(crate) const DEVICE_STARTED: &str = "soundserver: resumed"; /// The T14's panic, staged on its own HDA ring: a client that stops producing /// for longer than the DMA ring takes to come round. The engine replays every -/// buffer it completes, so soundd has to fill the periods the client did not +/// buffer it completes, so soundserver has to fill the periods the client did not /// cover (`underruns`) and may hold none of them back (`deferred`), across a /// suspend and a resume. /// /// The resume is the second stream's, which the job stages. Whether the first -/// stream finds soundd suspended is the job before it: on a shared boot it can -/// open while soundd still plays that job's tail out. +/// stream finds soundserver suspended is the job before it: on a shared boot it can +/// open while soundserver still plays that job's tail out. pub fn client_stall_on_metal(log: &Serial) -> Result<(), String> { const JOB: &str = "test_rs_hda_client_stall"; log.must_not_say("repeated completion for free buffer")?; @@ -121,27 +121,27 @@ pub fn client_stall_on_metal(log: &Serial) -> Result<(), String> { a suspended daemon, so nothing here tests a resume:\n{window}" )); } - if !window.contains("soundd: wakes=") { - return Err(format!("soundd reported no stats window while the client ran:\n{window}")); + if !window.contains("soundserver: wakes=") { + return Err(format!("soundserver reported no stats window while the client ran:\n{window}")); } if sum_field(window, "underruns") == 0 { return Err(format!( - "soundd filled no period the stalled client had not covered, so this boot staged \ + "soundserver filled no period the stalled client had not covered, so this boot staged \ nothing:\n{window}" )); } let deferred = sum_field(window, "deferred"); if deferred != 0 { return Err(format!( - "soundd deferred {deferred} period(s) on a ring that replays every one and completes \ + "soundserver deferred {deferred} period(s) on a ring that replays every one and completes \ it again, which is the panic this exists for:\n{window}" )); } Ok(()) } -/// Two clients through soundd, and what soundd said about each leaving: every -/// removal names a departure soundd established, and none claims a death. +/// Two clients through soundserver, and what soundserver said about each leaving: every +/// removal names a departure soundserver established, and none claims a death. pub fn departures_on_metal(log: &Serial) -> Result<(), String> { const CLIENTS: usize = 2; let window = job_window(log.text(), "test_rs_null_sink_client_exits", CLIENTS)?; @@ -152,7 +152,7 @@ pub fn departures_on_metal(log: &Serial) -> Result<(), String> { Err(format!("{}\n{window}", problems.join("\n"))) } -/// Sum one `soundd:` counter across every stats window. +/// Sum one `soundserver:` counter across every stats window. fn sum_field(serial: &str, key: &str) -> u32 { let needle = format!(" {key}="); serial @@ -165,15 +165,15 @@ fn sum_field(serial: &str, key: &str) -> u32 { .sum() } -/// Every way a client left, as soundd reported it: one entry per -/// `soundd: client {id} removed ({how})` in `serial`. +/// Every way a client left, as soundserver reported it: one entry per +/// `soundserver: client {id} removed ({how})` in `serial`. /// /// The reason is read from the same line — a removal that names none yields the /// empty string, which is what [`check_departures`] reds on. fn departures(serial: &str) -> Vec { serial .lines() - .filter(|l| l.contains("soundd: client ") && l.contains(" removed")) + .filter(|l| l.contains("soundserver: client ") && l.contains(" removed")) .map(|l| { let after = l.split(" removed").nth(1).unwrap_or("").trim(); after @@ -185,7 +185,7 @@ fn departures(serial: &str) -> Vec { .collect() } -/// **soundd may not report a departure it did not establish.** +/// **soundserver may not report a departure it did not establish.** /// /// A crash and a clean exit close the same descriptors in the same order, so /// the mix loop's broken signal pipe witnesses neither — it used to say `died` @@ -203,24 +203,24 @@ fn check_departures(serial: &str, expect: usize) -> Vec { let seen = departures(serial); if seen.len() != expect { problems.push(format!( - "soundd reported {} client removals, expected {expect}", + "soundserver reported {} client removals, expected {expect}", seen.len() )); } for how in &seen { if !KNOWN.contains(&how.as_str()) { problems.push(format!( - "a client was removed with no departure soundd established ({how:?}); \ - the four soundd establishes are {KNOWN:?}" + "a client was removed with no departure soundserver established ({how:?}); \ + the four soundserver establishes are {KNOWN:?}" )); } } - // The word itself, whatever line carries it: soundd cannot see a death and + // The word itself, whatever line carries it: soundserver cannot see a death and // must not print one. - for line in serial.lines().filter(|l| l.contains("soundd: ")) { + for line in serial.lines().filter(|l| l.contains("soundserver: ")) { if line.contains(" died") || line.contains(" crashed") { problems.push(format!( - "soundd claimed a client death it cannot distinguish from a clean exit: \ + "soundserver claimed a client death it cannot distinguish from a clean exit: \ {line:?}" )); } @@ -228,28 +228,28 @@ fn check_departures(serial: &str, expect: usize) -> Vec { problems } -/// soundd's mix thread never waits on the log: `tests/logstallcase`'s `logd` -/// reads nothing of soundd's until the job says the tone has played, and the -/// job fills soundd's ring with soundd's own refusals before it plays. Judged +/// soundserver's mix thread never waits on the log: `tests/logstallcase`'s `logkeeper` +/// reads nothing of soundserver's until the job says the tone has played, and the +/// job fills soundserver's ring with soundserver's own refusals before it plays. Judged /// off `/log`: /// -/// 1. **The ring was full** — the premise: `logd` found every one of its slots +/// 1. **The ring was full** — the premise: `logkeeper` found every one of its slots /// waiting when the stall ended. -/// 2. **Nothing went unwritten silently**: every line soundd's control thread -/// said after the boot is in `/log` or among the records `logd` counted +/// 2. **Nothing went unwritten silently**: every line soundserver's control thread +/// said after the boot is in `/log` or among the records `logkeeper` counted /// unwritten, exactly, and some were counted — the flood is larger than the /// ring. pub fn log_stall_on_metal(log: &Serial) -> Result<(), String> { - const REFUSAL: &str = "soundd: refusing connection,"; - // `logd`'s counts of soundd's shared-ring records it could not write: its + const REFUSAL: &str = "soundserver: refusing connection,"; + // `logkeeper`'s counts of soundserver's shared-ring records it could not write: its // lanes are the mix thread's, counted apart. const UNWRITTEN: [&str; 2] = - [" record(s) of soundd's found its ring full", " record(s) of soundd's past its"]; - const RELEASED: &str = "logd: reading soundd again, as `--stall-until` asked, with "; + [" record(s) of soundserver's found its ring full", " record(s) of soundserver's past its"]; + const RELEASED: &str = "logkeeper: reading soundserver again, as `--stall-until` asked, with "; const OF_SLOTS: &str = " of its ring's "; // The control thread's lines after the flood that are not refusals: the // probe it accepted, and the tone's stream. Either is in `/log` or counted. - const AFTER_FLOOD: [&str; 2] = ["soundd: protocol violation (msg ", "soundd: opening stream: "]; + const AFTER_FLOOD: [&str; 2] = ["soundserver: protocol violation (msg ", "soundserver: opening stream: "]; let number_before = |line: &str, marker: &str| -> Option { let at = line.find(marker)?; line[..at].rsplit(' ').next()?.parse().ok() @@ -264,13 +264,13 @@ pub fn log_stall_on_metal(log: &Serial) -> Result<(), String> { .find_map(|l| number_after(l, marker)) .ok_or_else(|| format!("the job never said {marker:?}:\n{text}")) }; - // Every refusal the job heard or provoked is one line soundd said. - let owed = said_by_job("flooded soundd with ")? + said_by_job("soundd refused ")?; + // Every refusal the job heard or provoked is one line soundserver said. + let owed = said_by_job("flooded soundserver with ")? + said_by_job("soundserver refused ")?; let (mut refusals, mut unsaid, mut others, mut waiting) = (0u64, 0u64, 0u64, None); - let soundd = toyos_build::bootlog::lines_of(text, "soundd"); - let logd = toyos_build::bootlog::lines_of(text, "logd"); - for line in soundd.lines().chain(logd.lines()) { + let soundserver = toyos_build::bootlog::lines_of(text, "soundserver"); + let logkeeper = toyos_build::bootlog::lines_of(text, "logkeeper"); + for line in soundserver.lines().chain(logkeeper.lines()) { if line.contains(REFUSAL) { refusals += 1; } @@ -286,17 +286,17 @@ pub fn log_stall_on_metal(log: &Serial) -> Result<(), String> { Some((held, slots)) if held == slots && slots > 0 => {} Some((held, slots)) => { return Err(format!( - "logd found {held} of soundd's {slots} ring slots waiting when its stall ended: \ + "logkeeper found {held} of soundserver's {slots} ring slots waiting when its stall ended: \ the tone was not played to a full ring" )) } - None => return Err("/log never says logd's stall on soundd ended".to_string()), + None => return Err("/log never says logkeeper's stall on soundserver ended".to_string()), } let said = owed + AFTER_FLOOD.len() as u64; if refusals + others + unsaid != said || unsaid == 0 { return Err(format!( - "soundd's control thread said {said} lines after the boot ({owed} refusals and {} \ - others); /log holds {refusals} refusals and {others} of the others, and logd \ + "soundserver's control thread said {said} lines after the boot ({owed} refusals and {} \ + others); /log holds {refusals} refusals and {others} of the others, and logkeeper \ counted {unsaid} unwritten", AFTER_FLOOD.len(), )); diff --git a/tests/common/iommu.rs b/tests/common/iommu.rs index 3296f638f2a..351c3da5d66 100644 --- a/tests/common/iommu.rs +++ b/tests/common/iommu.rs @@ -8,13 +8,13 @@ use std::path::Path; use super::qemu::{self, BootOptions, Profile, QemuInstance}; use super::serial::Serial; -/// The function `tests/netcase`'s netd claims, as its `devices` row spells it. -const NETD_CLAIMS: &str = "1af4:1041"; +/// The function `tests/netcase`'s netstack claims, as its `devices` row spells it. +const NETSTACK_CLAIMS: &str = "1af4:1041"; -/// fsd's word for DATA's directories served from memory. +/// fileserver's word for DATA's directories served from memory. const IN_MEMORY: &str = "are in memory and will not survive a reboot"; -/// The boot config that runs `netd` with a virtio NIC in front of it. +/// The boot config that runs `netstack` with a virtio NIC in front of it. fn netcase() -> std::path::PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/netcase") } @@ -63,12 +63,12 @@ pub fn iommu_virtio_platform(test_config: &Path) -> Result<(), String> { // `netcase`: the NIC's driver is a process, and this is the one config // that runs it. A daemon's line is waited for on the stream: the boot // log ends at test-runner's `===READY===`, its first act, and nothing - // orders that against what the programs init started before it print. + // orders that against what the programs the supervisor started before it print. let mut qemu = QemuInstance::boot_with_options(&netcase(), &[], &[], options); let said: &[&str] = if behind_unit { - &[CLAIM_BOUNDED, NETD_NEGOTIATED] + &[CLAIM_BOUNDED, NETSTACK_NEGOTIATED] } else { - &[BLOCKD_REFUSED, FSD_WITHOUT_DATA] + &[DISKSERVER_REFUSED, FILESERVER_WITHOUT_DATA] }; let mut text = qemu.boot_log().to_string(); qemu::await_guest(&mut qemu, &mut text, &format!("{name}: {said:?}"), |t| { @@ -78,7 +78,7 @@ pub fn iommu_virtio_platform(test_config: &Path) -> Result<(), String> { let log = Serial::named("boot console", text); log.must_be_clean()?; log.must_say("Boot: complete")?; - log.must_say("init: started netd")?; + log.must_say("supervisor: started netstack")?; // **Whether the NIC's function is handed to a process at all is the // machine's answer, not a choice.** A process driving a device writes @@ -88,10 +88,10 @@ pub fn iommu_virtio_platform(test_config: &Path) -> Result<(), String> { // unit has three negotiators, one of them across the boundary, and the // arm without one has two and a refusal. let expected = if behind_unit { - // And the claim netd was given is bounded to its own function's + // And the claim netstack was given is bounded to its own function's // configuration space, which is what makes its capability walk — // an index by numbers the *device* wrote — safe to run at all. - // netd asks the kernel for a read past the end, one straddling it + // netstack asks the kernel for a read past the end, one straddling it // and one misaligned, and refuses to drive a claim that answers any // of them. log.must_say(CLAIM_BOUNDED)?; @@ -159,19 +159,19 @@ pub fn iommu_virtio_platform(test_config: &Path) -> Result<(), String> { declining_is_not_free(test_config) } -/// netd's, once its claim answers nothing outside its own function. +/// netstack's, once its claim answers nothing outside its own function. const CLAIM_BOUNDED: &str = - "netd: this claim answers 4096 bytes of configuration space and refuses every access \ + "netstack: this claim answers 4096 bytes of configuration space and refuses every access \ outside them"; -/// netd's feature line, the kernel's shape under netd's name. -const NETD_NEGOTIATED: &str = "netd: VirtIO: PCI "; -const BLOCKD_REFUSED: &str = - "blockd: NOT SERVING — pci:1b36:0010 is on this machine and the kernel refused this service its claim"; -const FSD_WITHOUT_DATA: &str = - "fsd: the block service would not list its partitions (Refused(ClaimRefused)); DATA is absent this boot"; +/// netstack's feature line, the kernel's shape under netstack's name. +const NETSTACK_NEGOTIATED: &str = "netstack: VirtIO: PCI "; +const DISKSERVER_REFUSED: &str = + "diskserver: NOT SERVING — pci:1b36:0010 is on this machine and the kernel refused this service its claim"; +const FILESERVER_WITHOUT_DATA: &str = + "fileserver: the block service would not list its partitions (Refused(ClaimRefused)); DATA is absent this boot"; /// The slot QEMU's `-device` order puts `tests/netcase`'s NVMe controller on, -/// the one its blockd row claims. +/// the one its diskserver row claims. const NVME_AT: &str = "00:02.0"; /// **A machine with no unit hands no function to a process**, and says so @@ -181,19 +181,19 @@ const NVME_AT: &str = "00:02.0"; /// (`issues/kernel/every-driver-is-still-in-the-kernel.md`) is that moving a /// driver out without translation costs security: a descriptor holding a /// physical address is an arbitrary read and write over all of memory. So the -/// kernel refuses the claim by name, init says which device it could not mint, -/// and netd exits rather than driving anything — and the machine finishes +/// kernel refuses the claim by name, the supervisor says which device it could not mint, +/// and netstack exits rather than driving anything — and the machine finishes /// booting, which is the half a refusal that panicked would fail. The NVMe /// controller is refused the same, and DATA with it by name: a disk that is /// there and cannot be used is never answered with memory. fn no_unit_is_no_claim(log: &Serial) -> Result<(), String> { const NO_DOMAIN: &str = "it would have no address space of its own"; - // netd's own exit is the third saying, and is not read here. - refused_claim(log, NETD_CLAIMS, NO_DOMAIN, &[NVME_AT])?; + // netstack's own exit is the third saying, and is not read here. + refused_claim(log, NETSTACK_CLAIMS, NO_DOMAIN, &[NVME_AT])?; log.must_say(&format!("pcidev: PCI {NVME_AT} NOT HANDED OVER — {NO_DOMAIN}"))?; - log.must_say("init: blockd: pci:1b36:0010 is on this machine and could not be handed over")?; - log.must_say(BLOCKD_REFUSED)?; - log.must_say(FSD_WITHOUT_DATA)?; + log.must_say("supervisor: diskserver: pci:1b36:0010 is on this machine and could not be handed over")?; + log.must_say(DISKSERVER_REFUSED)?; + log.must_say(FILESERVER_WITHOUT_DATA)?; log.must_not_say(IN_MEMORY)?; // And this machine handed *nothing* over, which is more than the claim's // own refusal says: with no unit there is no function any process could be @@ -243,7 +243,7 @@ fn declining_is_not_free(test_config: &Path) -> Result<(), String> { Ok(()) } -/// The slot QEMU's `-device` order puts the function netd claims on, and the +/// The slot QEMU's `-device` order puts the function netstack claims on, and the /// address every judge below is an assertion about. /// /// **The address is the harness's own and never the guest's.** A judge that @@ -296,7 +296,7 @@ fn functions_named<'a>(log: &'a Serial, marker: &str) -> Result, St /// **The claim on [`CLAIMED_AT`] was refused for `why`, and the refusal spent /// nothing**: no BAR of that function moved, neither of its two message -/// mechanisms is armed, `claims` reached no holder, and init said so in the +/// mechanisms is armed, `claims` reached no holder, and the supervisor said so in the /// boot config's own spelling. `beside` is every other function this machine /// refuses, each judged by its own caller. /// @@ -320,11 +320,11 @@ fn refused_claim(log: &Serial, claims: &str, why: &str, beside: &[&str]) -> Resu log.must_not_say(&msi_armed())?; log.must_not_say(&bar_moved())?; // All the way out to userland, rather than a kernel that logged a refusal - // and handed netd a NIC anyway. init names what it could not mint in the + // and handed netstack a NIC anyway. The supervisor names what it could not mint in the // config's own spelling, and **with this refusal's own word**: the machine // has the function, so "no such device on this machine" would be false. log.must_say(&format!( - "init: netd: pci:{claims} is on this machine and could not be handed over" + "supervisor: netstack: pci:{claims} is on this machine and could not be handed over" ))?; Ok(()) } diff --git a/tests/common/lan.rs b/tests/common/lan.rs index b531fe13106..d8b9264403b 100644 --- a/tests/common/lan.rs +++ b/tests/common/lan.rs @@ -1,34 +1,34 @@ -//! The cable: netd taking this machine's address from the network, and the T14 +//! The cable: netstack taking this machine's address from the network, and the T14 //! answering the development host on it. //! //! Every line read here is a line of a boot's log — the kernel's records, and -//! netd's own lines, which reach the stick under netd's name through its log -//! ring — or the one file netd leaves beside them, the lease probe's -//! report. The judge reads netd's lines by that name and no other program's. +//! netstack's own lines, which reach the stick under netstack's name through its log +//! ring — or the one file netstack leaves beside them, the lease probe's +//! report. The judge reads netstack's lines by that name and no other program's. use toyos_build::lan::{lease_in, link_up_ms, LINK_UP, MAC, READY}; use toyos_i219::lease::{self, Event, Verdict}; use super::metal; -/// The boot with netd's `--exit-with-lease` armed: netd brings the card up and +/// The boot with netstack's `--exit-with-lease` armed: netstack brings the card up and /// serves, leaves [`LEASE_FILE`] on the log volume one durable line at a time, /// and ends with the lease's verdict as its exit code, which the kernel's /// `exit:` record carries off a machine whose console reaches nobody. pub const LEASE_CONFIG: &str = "tests/lanleasecase"; pub const LEASE_BOOT: &str = "lanleasecase"; -/// The file that report is left in, at the root of the log volume — netd's +/// The file that report is left in, at the root of the log volume — netstack's /// `report::PATH` under `/log`. pub const LEASE_FILE: &str = "lease.txt"; -/// netd, as the kernel's `exit:` record names it. -const NETD: &str = "netd"; +/// netstack, as the kernel's `exit:` record names it. +const NETSTACK: &str = "netstack"; /// The one job on that boot: it holds the machine up. pub const JOBS: &[&str] = &["test_rs_lan_hold"]; -/// The boot the host talks to over its own cable: the log it serves, sshd, and +/// The boot the host talks to over its own cable: the log it serves, sshserver, and /// `reboot` as the way the machine is handed back. pub const TALK_CONFIG: &str = "tests/lantalkcase"; pub const TALK_BOOT: &str = "lantalkcase"; @@ -54,9 +54,9 @@ const ID: &str = "8086:15fc"; /// the metal loop reads the cable and the card's MAC before the flash. pub const NIC: &str = "0000:00:1f.6"; -/// The T14's judge: the claim, the card, and the lease in netd's own lines. +/// The T14's judge: the claim, the card, and the lease in netstack's own lines. /// -/// **The host learns the leased address from the boot**: netd answers for the +/// **The host learns the leased address from the boot**: netstack answers for the /// machine's name once it holds a lease, and the loop reads the log served at /// the address the name answered with. The lease record is held to that /// address here, so no lease but this boot's own is judged. @@ -87,17 +87,17 @@ pub fn on_metal(back: &metal::Readback) -> Result<(), String> { }), } - // netd's own records, in the form the kernel gives a program's, under netd's tag. + // netstack's own records, in the form the kernel gives a program's, under netstack's tag. let log = back.log(); - let netd = toyos_build::lan::netd_records(log.text()); + let netstack = toyos_build::lan::netstack_records(log.text()); for owed in [MAC, LINK_UP, READY] { - if !netd.contains(owed) { + if !netstack.contains(owed) { bad.push(format!("no {owed:?} record")); } } // Neither MAC is printed: a judge's lines are quoted in public. - if !netd.contains(&format!("{MAC}{wire_mac}")) { + if !netstack.contains(&format!("{MAC}{wire_mac}")) { bad.push(format!( "no {MAC:?} record names the MAC the operating system before this boot read on \ {NIC}, which is `{}` in its `{}`: the card this boot brought up is not that one", @@ -106,12 +106,12 @@ pub fn on_metal(back: &metal::Readback) -> Result<(), String> { )); } - match link_up_ms(&netd) { + match link_up_ms(&netstack) { Ok(ms) => eprintln!(" [lan] the link came up {ms} ms after the driver did"), Err(why) => bad.push(why), } - match lease_in(&netd) { + match lease_in(&netstack) { Ok(lease) => { // The resolvers are counted and not printed, for the same reason. eprintln!( @@ -126,7 +126,7 @@ pub fn on_metal(back: &metal::Readback) -> Result<(), String> { if lease.address != heard.peer { bad.push(format!( "this boot leased {} and answered for its name at {}: the address the host \ - reached it at is not the one netd says it leased", + reached it at is not the one netstack says it leased", lease.address, heard.peer )); } @@ -140,13 +140,13 @@ pub fn on_metal(back: &metal::Readback) -> Result<(), String> { Err(format!("{} finding(s):\n {}", bad.len(), bad.join("\n "))) } -/// The lease probe's judge: netd's exit code, decoded through the table the +/// The lease probe's judge: netstack's exit code, decoded through the table the /// driver crate owns, and the report it left on the log volume — the lease, /// the router, and what the driver and the MAC counted each way. A code that is /// no lease is a finding by its name, which the shipping boot's silence cannot /// give. pub fn leased_on_metal(back: &metal::Readback) -> Result<(), String> { - let code = back.exit_code(NETD)?; + let code = back.exit_code(NETSTACK)?; let text = back .log_volume_file(LEASE_FILE)? .ok_or_else(|| format!("{LEASE_BOOT}'s log volume carries no {LEASE_FILE}"))?; @@ -156,23 +156,23 @@ pub fn leased_on_metal(back: &metal::Readback) -> Result<(), String> { let summary = lease::summary(&text).map_err(|why| format!("{LEASE_FILE}: {why}"))?; if summary.exit != Some(code) { return Err(format!( - "netd exited {code} and its report ends in {:?}: the two records of one exit disagree", + "netstack exited {code} and its report ends in {:?}: the two records of one exit disagree", summary.exit )); } match Verdict::from_exit_code(code) { Some(Verdict::Leased) => {} - Some(other) => return Err(format!("netd exited {code} on {LEASE_BOOT}: {other}")), + Some(other) => return Err(format!("netstack exited {code} on {LEASE_BOOT}: {other}")), None => { - return Err(format!("netd exited {code} on {LEASE_BOOT}, which is no verdict the probe encodes")) + return Err(format!("netstack exited {code} on {LEASE_BOOT}, which is no verdict the probe encodes")) } } let Some((ms, Event::Leased { address, prefix, server, router })) = summary.lease else { - return Err(format!("netd exited leased and {LEASE_FILE} records no lease")); + return Err(format!("netstack exited leased and {LEASE_FILE} records no lease")); }; let counts = summary.counts.ok_or_else(|| format!("{LEASE_FILE} carries no counts"))?; eprintln!( - " [lan] leased {address}/{prefix} from {server}, router {router:?}, {ms} ms after netd \ + " [lan] leased {address}/{prefix} from {server}, router {router:?}, {ms} ms after netstack \ started; the driver counted {} sent and {} received, the MAC {} sent, {} received of \ {} seen", counts.sent, counts.received, counts.wire.sent, counts.wire.received, counts.wire.seen @@ -195,7 +195,7 @@ pub fn talked_on_metal(back: &metal::Readback) -> Result<(), String> { Ok(said) => said.iter().for_each(|line| eprintln!(" [talk] {line}")), Err(found) => bad.extend(found), } - // **The stick is the oracle the wire is compared with**: `logd` writes a + // **The stick is the oracle the wire is compared with**: `logkeeper` writes a // round to `/log` and then hands it to every reader from the boot's first // line, so what arrived is the file's own first lines in the file's own // order — and the file came back over a different path. diff --git a/tests/common/logstream.rs b/tests/common/logstream.rs index bb6976aee24..ae206e6470d 100644 --- a/tests/common/logstream.rs +++ b/tests/common/logstream.rs @@ -1,8 +1,8 @@ -//! The log a machine serves, judged from the host: a guest whose `logd` port +//! The log a machine serves, judged from the host: a guest whose `logkeeper` port //! is forwarded, a reader that connects when the test says so, and the guest's //! own `/log` as the oracle. //! -//! **The file is what the stream is judged against.** `logd` writes each round +//! **The file is what the stream is judged against.** `logkeeper` writes each round //! to `/log` and then hands the same bytes to every reader, from the boot's //! first line however late the reader came, so what a reader received is the //! file's own first lines in the file's own order ([`is_prefix_of`]). The file diff --git a/tests/common/metal.rs b/tests/common/metal.rs index 178444ee2c7..ce05cb2f6ad 100644 --- a/tests/common/metal.rs +++ b/tests/common/metal.rs @@ -179,13 +179,13 @@ pub struct Readback { /// The directory the loop wrote this boot's files into. home: PathBuf, loader: String, - /// The kernel's own records of every `logd` file this boot wrote. + /// The kernel's own records of every `logkeeper` file this boot wrote. kernel: String, /// Every line of those files, the programs' included. log: String, /// `Boot: complete (Nms)`, or `None` on a boot that never got there. pub boot_ms: Option, - /// What the machine spent getting back to `sshd`. + /// What the machine spent getting back to Ubuntu's ssh server. pub back_secs: u64, /// How long after that the boot stick's own partition was there again. pub stick_secs: u64, @@ -201,7 +201,7 @@ pub struct Readback { impl Readback { /// One boot's readback out of the three files the loop wrote for it: - /// `loader.log`, the `logd` files as one text, and the boot file. + /// `loader.log`, the `logkeeper` files as one text, and the boot file. pub fn new(label: &str, home: PathBuf, loader: String, log: String, boot: &str) -> Result { let kernel = bootlog::kernel_records(&log); let back_secs = toyos_build::metal::back_secs(boot) @@ -243,7 +243,7 @@ impl Readback { Ok((heard, stream.split_inclusive('\n').map(str::to_string).collect())) } - /// One file off the log volume that is neither the loader's nor `logd`'s, + /// One file off the log volume that is neither the loader's nor `logkeeper`'s, /// read out of the partition's own bytes; `None` where the volume has no /// such file. /// @@ -261,9 +261,9 @@ impl Readback { .transpose() } - /// Every `logd` file this boot wrote, as one text, less every program's + /// Every `logkeeper` file this boot wrote, as one text, less every program's /// line ([`bootlog::kernel_records`]): no program's line is read as the kernel's. - /// It ends where init had `logd` make it whole, so what the kernel writes + /// It ends where the supervisor had `logkeeper` make it whole, so what the kernel writes /// inside the stop or a wedge is only on the page ([`Self::after_the_reset`]). pub fn kernel(&self) -> Serial { Serial::named(&format!("{}'s kernel log", self.label), self.kernel.as_str()) @@ -289,8 +289,8 @@ impl Readback { /// Whether this boot's log is whole to its stop, and the stop's own tail /// is on the page. /// - /// **The file ends where init had `logd` make it whole.** The stop stops - /// `logd` with every other thread, so what the kernel says from there on + /// **The file ends where the supervisor had `logkeeper` make it whole.** The stop stops + /// `logkeeper` with every other thread, so what the kernel says from there on /// goes on the black-box page under the boot's `DONE` seal and comes back /// in the next loader pass, and this reads it there — for every boot, /// because the suite's whole verdict is read out of those two files. @@ -305,7 +305,7 @@ impl Readback { } if bootlog::stopping_line(&self.log).is_none() { return Err(format!( - "{}'s pass after the reset read DONE, and its log carries no {:?} from init: \ + "{}'s pass after the reset read DONE, and its log carries no {:?} from the supervisor: \ nothing made the file whole before the stop", self.label, bootlog::STOPPING, @@ -340,7 +340,7 @@ impl Readback { /// What the on-screen panel cost this boot, off the kernel's own census. /// /// **Off the page, because no file carries it.** A boot that hands the - /// machine back writes the census inside its stop, after `logd` has + /// machine back writes the census inside its stop, after `logkeeper` has /// stopped, and seals it among its tail; a boot a bound ended seals it with /// its record. The page from *this* boot is the one after the separator: /// an earlier chain's report can sit in the pass before it. @@ -361,7 +361,7 @@ impl Readback { } /// The stop's own record, off the page its tail is sealed on: the stop - /// writes it after `logd` has stopped, so no file carries it. + /// writes it after `logkeeper` has stopped, so no file carries it. fn stop_record(&self) -> Option { toyos_build::metal::park(self.after_the_reset().ok()?.text()) } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 1e861455f0d..11a7116b285 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -9,7 +9,7 @@ pub mod iommu; pub mod irqcensus; /// The `isa` claim's rows on the T14. pub mod isa; -/// The cable: netd's address, and the T14 answering the host on it. +/// The cable: netstack's address, and the T14 answering the host on it. pub mod lan; pub mod logstream; pub mod metal; diff --git a/tests/common/power.rs b/tests/common/power.rs index 27008fa3fea..cc369b2179f 100644 --- a/tests/common/power.rs +++ b/tests/common/power.rs @@ -238,7 +238,7 @@ pub fn done_chain(after: &serial::Serial) -> Result<(), String> { } /// The tail the stop sealed under the seal: the one channel for what the -/// kernel said after `logd` stopped — its stop record, the panel's census, and +/// kernel said after `logkeeper` stopped — its stop record, the panel's census, and /// the last word. Read after the seal, /// because the same lines are in the capture on the first boot's console. fn the_tail_is_the_stops(after: &serial::Serial) -> Result<(), String> { @@ -272,7 +272,7 @@ fn the_tail_is_the_stops(after: &serial::Serial) -> Result<(), String> { pub fn usb_load_chain(after: &serial::Serial) -> Result<(), String> { after.must_say(bootlog::PREVIOUS_PANIC)?; after.must_say_after(bootlog::PREVIOUS_PANIC, bootlog::DEADLINE_EXPIRED)?; - // The sweep starts inside the stop, after init had the file made whole, so + // The sweep starts inside the stop, after the supervisor had the file made whole, so // its records cross only in the page's tail. after.must_say_after(bootlog::PREVIOUS_PANIC, bootlog::USB_LOAD_RUNNING)?; // A sweep that refused, one the disk stopped answering, and one that swept @@ -305,8 +305,8 @@ pub fn usb_load_chain(after: &serial::Serial) -> Result<(), String> { /// The metal half of [`boot_deadline_ends_a_wedge`]: a T14 boot that wedged on /// purpose ended itself, and the pass after the reset read why off the page. /// -/// **The only evidence a wedge can leave on this machine.** `logd` writes the -/// kernel log to the stick, and a wedged boot's `logd` never runs again — so +/// **The only evidence a wedge can leave on this machine.** `logkeeper` writes the +/// kernel log to the stick, and a wedged boot's `logkeeper` never runs again — so /// everything after the wedge exists only in the record ring, and the black box /// is the one channel that carries a copy of it across the reset. pub fn deadline_wedge_chain(after: &serial::Serial) -> Result<(), String> { @@ -349,7 +349,7 @@ pub fn hard_lockup_chain( kernel: &serial::Serial, after: &serial::Serial, ) -> Result<(), String> { - // **Nothing this judge reads was written after the wedge.** `logd` stops + // **Nothing this judge reads was written after the wedge.** `logkeeper` stops // where the scheduler does, so the stick's kernel log ends at the last // spawn, and the sealed page can fill with a boot's *older* records before // it reaches the lines the control writes about itself. What crosses is the diff --git a/tests/common/qemu.rs b/tests/common/qemu.rs index 9f756c2bc8c..8847ed12e05 100644 --- a/tests/common/qemu.rs +++ b/tests/common/qemu.rs @@ -356,7 +356,7 @@ pub const TIMED_OUT: &str = "timed out after"; /// How long a guest may say nothing before a wait on it is a stall. /// /// Every config these waits run on has something on a periodic interval — the -/// compositor's frame batch and soundd's stats window are both about 2 s — so +/// compositor's frame batch and soundserver's stats window are both about 2 s — so /// silence here is a machine that has stopped rather than a machine that is /// thinking. It is not a verdict about any of them: no assertion in this suite /// is satisfied by the guest merely talking. @@ -490,7 +490,7 @@ pub const VERDICT_POLL: Duration = Duration::from_millis(100); /// **`elapsed > ceiling` stays a necessary condition, and that is what keeps /// this safe.** Silence alone is not a wedge on this suite's boots: a healthy /// but idle guest on a config with no live periodic speaker — no compositor, an -/// idle soundd, and the kernel's own ~10 s line halting with the idle loop — was +/// idle soundserver, and the kernel's own ~10 s line halting with the idle loop — was /// measured quiet for as long as 102 s, so a guard that fired on 15 s of silence /// by itself would red a working machine. A guest's own budget is what says how /// long its silence is allowed; only past *that* does quiet mean stopped. @@ -950,7 +950,7 @@ impl BootOptions { /// The in-guest test runner's startup marker. /// -/// It is that runner's own first line and nothing else's. Init spawns its +/// It is that runner's own first line and nothing else's. The supervisor spawns its /// programs without waiting, so this marker orders nothing about any other /// program's startup — a test asking about a daemon's line waits on the guest /// for that line ([`await_guest`]), never on a span of host wall clock after @@ -1135,14 +1135,14 @@ pub fn build_toyos_bin(arch: Arch, crate_path: &Path, name: &str) -> Vec { /// A kernel record's line, whichever writer spelled its head: `klogd`'s console /// `[kernel …]` and a `/log` file's `[