Repository navigation
ToyOS designates its own DATA partition: one GPT writer, the driver judges and stamps under a signed image's authorization - #1085
Conversation
`toyos_gpt::edit` is the one GPT writer in the tree, which the disk drivers will edit their own tables with: a `Table` of 128 entries of 128 bytes, checked against everything UEFI 2.10 §5.3 requires (usable range, ranges, overlaps, zero and duplicate unique GUIDs, unused entries all zero), encoded with both CRCs, and laid by `Encoded::steps` as §5.3.2 requires: "Software must update the backup GPT before the primary GPT" — backup array and header, a flush, then LBA 0 when asked and the primary, then a flush. `read_copies` reads LBA 0 and each copy alone, so a caller sees which copy is in force and whether the two agree, rather than the first one that parsed. The flush between the copies is what keeps a crash from tearing both: the host model cuts the write after every step and inside every write at any subset of its sectors, and each cut reads through `toyos_gpt::list` as the old table or the new one, never neither or a mixture, with the primary never newer than the backup. Without the middle flush a cut leaves both copies failing their CRCs; with the primary first, the primary is newer than the backup — under this reader alone that still reads as old or new, which is why the order is asserted as the specification's own invariant. `build/gptwrite.rs` goes: the build and the harness lay their tables with `image::write_gpt` over this writer, and the byte-for-byte oracle against the `gpt` crate moves to `lib/gpt/tests/edit.rs`, where that crate is already a dev-dependency. The designation stamp's encoder and reader are `bcachefs::designation` and `bcachefs::designated`, beside the magic they share, so the build, the file server and the drivers that will write it have one definition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… count floor goes UEFI 2.10 §5.3.1 puts the backup header on the device's last LBA. nvme and usbd read their table through a 4 KiB-block view whose count they floored, so on a disk whose sector count is not whole blocks — one bench stick has 7507812 512-byte sectors — the backup was never where the parser looked, and `toyos_gpt::Sectors::lba_count_granularity` existed to concede the difference. Both now read every sector: whole blocks where the block is whole, and the tail one sector at a time (nvme's `read_sectors`, usbd's READ(10) of the sectors the last block has). The concession has no reader left and goes, with the floored-device test machinery. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…self, under a token A disk driver is the one process that holds its device and reads its table, so it is where a designation is judged and carried out: the identity checked is the identity written through, with no path between. - Each disk's table state has a 128-bit random token, drawn at bring-up and again after every change the driver makes to the disk (`wire::Token`, `toyos_blockserve::draw_token`). An authorization is bound to one; a re-plug, a driver restart or a change made since refuses it `Stale`, so one is used at most once. - `Sessions::describe` answers a disk's size, its token, LBA 0 and each copy of the table as `toyos_gpt::edit::read_copies` read them, and every entry of the copy in force with whether a session holds it (`MSG_DISK`, `MSG_SLOT`, `MSG_DESCRIBED`). - `Sessions::designate` refuses a stale token, a partition the running system is on (`active`, the service's word) and one a session holds, then holds the partition for the job's length and runs `toyos_blockserve::designate`: read the front 1 MiB, judge it, and only for a partition it does not recognise and a request that commits, write the stamp as one whole block made in memory, flush, read it back and compare. `toyos_blockserve::content` refuses ToyOS's own volume, an existing stamp and the signatures of the formats it names: a bug fence, never a licence, since recognising nothing proves nothing. - `Link` hands over describe and designate work beside sessions (`disk::MSG_DESCRIBE`, `disk::MSG_DESIGNATE`), and the block service's badge gains `Tables` and `Designate` (`wire::Badge`). Neither opens a session, and a designation writes nothing a client chose. nvme and usbd serve both with no code of their own beyond the hand-over: the job reaches the device through the same `Device` every session does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r that holds the disk A connection's badge decides what it reaches (`wire::Badge`): a partitions grant lists and opens what it admits, as before; a tables badge lists every partition and has its driver describe a disk; a designation badge does the one designation it was minted for, on the one disk carrying its partition, and nothing else. Neither of the new two opens a session. The supervisor names the partitions the running system is on (`--active`), and the driver refuses to designate one of them. The client's side is `diskserver::tables`: `describe` and `designate`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the signed image grants `/system/bin/disks list` describes every disk the block service serves: its size, LBA 0, each copy of its table and every partition of the copy in force. `disks designate data [--commit]` has the machine's one DATA partition designated by the driver of its disk. Neither is authority of the program's own: each needs the authorization its row was minted (`toyos_manifest::authorize`), which the supervisor mints at every start of the row as a connector to the block service carrying that one badge. The build lets an authorization that changes a disk go only to a row no login can start, and no image this repository ships carries one: today only a signed test image's job designates. Interactive use waits for the administrative authorization every system change will share, and nothing disk-specific stands in for it (`issues/toyos-manages-its-own-partitions.md`). The designation is resolved when it is asked for, not when the row starts: the block service finds the one DATA partition among every disk it serves, refusing none, two, or a GUID two disks carry, and the driver of that disk judges it against its own table, its holds and the running system's partitions, which the supervisor names (`--active`), in the turn it begins. An image's preauthorization names a role, not a state a person reviewed, so there is nothing for a token to bind and none is carried; a plan-bound authorization brings one with the table edits it permits. A foreign DATA partition is served absent rather than from memory, which `issues/a-foreign-data-partition-is-answered-with-memory.md` asked for: `hostdisk::left_alone` reads the absent line and that the in-memory line is never said. The scratch disk `--adopt-scratch` writes is recorded as not served (`issues/the-scratch-disk-adopt-scratch-makes-is-not-served.md`). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e T14's row `tests/images/designatecase.toml` is the one image whose runner holds `designate:data`, so the authorization reaches no boot but the one that is for it, and its runner starts nothing a login could reach. - `the_data_partition_beside_the_stick_is_designated` (QEMU x86-64, `Profile::MetalBesideAHostDisk`): a judge-only `disks designate data` writes nothing, the committed one is written by the NVMe driver and read back, and after the stop the host reads the disk image: DATA begins with `bcachefs::designation` for its size and every other byte is as it was. The supervisor minting the authorization, the block service resolving and routing it and the driver's job are four processes and a claim no host build runs together. - `bench_data_designated` (named only, the T14): the same designation on the bench's own NVMe, and a second boot whose DATA file server formats what it stamped and serves it, never from memory. It retires the host stamp of #1079's `toyos-metal --designate-data`. A metal job is a binary name and its arguments: the runner's job list takes what its stdin path always took. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e block service's hand-over Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g it drops, and the table module says what is true `every_shipped_boot_config_is_covered` holds `ALL_CONFIGS` to the tree, so `tests/images/designatecase.toml` is in it and every config gate reads it. The driver changes no table yet, so a table is still served for the disk's life. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stick a bench boots carries 7507812 sectors, four past its last whole 4 KiB block, which is where UEFI puts its backup header. With the primary header torn, the table comes from there; with the count floored back to whole blocks, as it was, it is not read at all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…arries its arguments Two references the writer's move and the job-list change left stale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r1: PR #1085 at
|
…hat is true, and no unreachable disk state - The build refuses an authorization that changes a disk to a login authority too, not only to a row a login can start: a login authority's namespace reaches every program a login runs directly. Its test reds without the check. - `Lba0` and the head's LBA-0 word go: no disk without a served table is described today, so no consumer reaches them. They come with `Init`. - Comments corrected: an authorization is resolved each time it is used and lasts the row's life; the stamp authorises a file server's format; the two-copy write is whole only on a device that keeps sectors whole and honours its flush; `tables` is `disks`'s alone; the signature table names documents where they exist; `toyos-gpt` is the writer too, and is no kernel dependency. `random_guid` and `write_at` each have their own doc. - The link's frame is sized for every frame the service sends. - `bench_data_designated` runs on the AMD bench too, and on the T14 refuses a stick whose last sector would not read. - `issues/a-first-format-interrupted-mid-flush-can-leave-a-superblock-over-a-bitmap-it-never-wrote.md`: the cache writes block 0 first, so a format is not superblock-last on the medium. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r2: PR #1085 at
|
The supervisor makes the log whole before it syncs the file servers and stops the drivers, so what either says is in no file. It left the AMD designation's format unobservable in its own readback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…designated `nvme_leaves_the_benchs_disk_alone` held DATA foreign on every boot, so a bench whose DATA ToyOS has designated reds on every testcases boot: the AMD bench's #1089 testcases boot mounted its volume. Its claim is now that nothing on the bench's disk is touched but its ToyOS DATA partition — every NVMe session on that partition alone — and that DATA is left alone while it is foreign, and formatted or mounted and served as bcachefs once it is designated, never stood in for by memory. `hostdisk::left_alone` answers which of the three DATA was; the QEMU twin, whose disk is never designated and whose every byte is read back, still requires it foreign. Re-judged with it: the AMD's #1089 testcases readback and the T14's #1074 diag3 readback pass. A copy of the AMD's with an NVMe session on the host's root partition reds, as does one whose DATA is said to be in memory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r3: PR #1085 at
|
|
Orchestrator: landing at 05720ad. Reviews r1–r3 LAND. Metal: both benches designated through the ToyOS-native path (T14 and AMD bench_data_designated PASS), each next boot mounted the volume, and nvme_leaves_the_benchs_disk_alone re-judged PASS on both with two red controls. Host CI (105) and the QEMU twins are green at 05720ad. |
…bench's NVMe #1085 lets ToyOS designate its own DATA, and both benches' fourth partitions are designated and mounted. So the follow-up staged in #1079 lands. ToyOS's persistent filesystem is DATA's /home (bcachefs crate's format, through the DATA file server and the NVMe driver), medium nvme. persist runs its durable rows there, then files' cached operations as fs.disk.*, on both systems: Linux on its home, ext4 on the same NVMe. A row whose media differ still has no verdict, and these now agree. The osbench row refuses a boot whose DATA was not a TOYOS-DATA partition the NVMe driver serves, mounted and not absent. It also refuses the boot that formats a newly designated DATA as a run, stating the format's duration. ToyOS's files group keeps /tmp alone: /home is fs.disk now. The compare's setup reads fs.disk.served_by. The README states the disk rows' rules: - one NVMe for both; - each system's own filesystem, Linux's mount options recorded; - one durability: a sync returns after the device's cache is flushed, ToyOS's fsync covering its whole volume; - one cache state: every row's files are written in its run and read cached on both. #1085 already judges nvme_leaves_the_benchs_disk_alone against a designated DATA, so that part of the staged patch is superseded and dropped. Nothing here depends on #1095 (ToyOS booting off the internal NVMe); the judge finds DATA by the NVMe driver's partition line, wherever the boot came from. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem
ToyOS could not touch its own disks' partitions. The benches' DATA partitions were to be stamped from the bench's Linux: #1079 proposed
toyos-metal --designate-data, which is unmerged and has since dropped it. Scratch sticks are made withsgdisk(--adopt-scratch). A foreign DATA partition was answered with memory (issues/a-foreign-data-partition-is-answered-with-memory.md). Owner direction (2026-10-28): ToyOS manages its partitions itself.What this builds
toyos-gpt(toyos_gpt::edit). It covers the table model, everything UEFI 2.10 §5.3 requires of a table, encoding with both CRCs, and the write order §5.3.2 requires ("Software must update the backup GPT before the primary GPT"): backup, flush, primary, flush. It also reads each copy alone, so a caller sees which copy is in force and whether the two agree.build/gptwrite.rsis deleted; the build and the harness lay tables with it.lba_count_granularity) has no reader left and goes.toyos_blockserve::designate), so the identity checked is the identity written through.--active, from the loader's inventory), and one the table does not name or serve.toyos_blockserve::content: ToyOS's own volume, an existing stamp, and named foreign signatures, as a bug fence, never a licence); write one whole stamp block made in memory; flush; read it back and compare.Deviceas every session, so nvme and usbd need no code of their own.wire::Badge).Tableslists every partition and has a driver describe its disk.DesignateDatadoes one thing: the machine's one DATA partition, resolved when it is asked for (zero, two, or a GUID on two disks is refused). Neither opens a session./system/bin/disks:disks listanddisks designate data [--commit](without--commitit judges and writes nothing). It holds no authority of its own. Each command needs the authorization its row is minted (toyos_manifest::authorize). The supervisor mints it at each start of the row from the signed image'sauthorize = [...].bcachefs::designation/designated, used by the build, the file server and the drivers./apps,/config,/homeand/stateare absent on that boot. That closesissues/a-foreign-data-partition-is-answered-with-memory.md;hostdisk::left_alonereads the absent line and that the in-memory line is never said.Authorization: what is and is not built
no_shipped_boot_config_authorizes_a_disk_change, holds the shipped configs to carrying none.tests/images/designatecase.toml's runner holdsdesignate:data. The shippeddisksrow holdstables(read only).diskschanges nothing for a person at a shell or over ssh, and a login grants nothing. Its exit is the administrative authorization every system change will share (planning architect, 2026-10-28), recorded as stage 1 ofissues/toyos-manages-its-own-partitions.md. Nothing disk-specific stands in for it.Retires
toyos-metal --designate-data, unmerged, now dropped there): thebench_data_designatedrow stamps from inside ToyOS instead. Nothing on main had it.--adopt-scratch, onceInitlands (stage 3). Its table is not served today, because sgdisk's partition is not whole 4 KiB blocks (issues/the-scratch-disk-adopt-scratch-makes-is-not-served.md, read from a bench boot's log).Checks
Each line gives the command, the exit code and the revision it ran at.
05720ad63:nvme_leaves_the_benchs_disk_alonenow claims nothing on the bench's disk is touched but its ToyOS DATA partition. DATA is left alone while foreign, formatted or mounted as bcachefs once designated, and never stood in for by memory.--ci host: exit 0, 105 steps.0343c0aa8:cargo run -- --ci host: exit 0, 105 steps green.cargo run -- --build-only: exit 0.cargo test --test toyos-build -- the_data_partition_beside_the_stick_is_designated a_host_disk_beside_the_stick_is_left_alone): exit 0.cargo testof-p toyos-gpt,toyos-blockring,toyos-blockserve,diskserver,disks,toyos-manifest,bcachefs,toyos-xhci,fileserverandtoyos-metal: exit 0 each.--ci hostexit 0 atfe22e03c6. The first run, ata72018eb9, exited 1 on an uncovered config and a redundant clone.3757d0da1.a_disk_changing_authorization_goes_to_no_row_a_login_can_startreds.designation of …: Written. The host reads the disk image after the stop: DATA's block 0 is exactlybcachefs::designation, and no other byte changed.Profile::MetalBesideAHostDisk. No AArch64 configuration carries that disk.bench_data_designatedjudged PASS at0343c0aa8. Boot 1: the NVMe driver wrote and read back the stamp on p4 (600 GiB). Boot 2: the file server formatted it and served bcachefs. The next boot (osbench: the comparison measures the systems, not the setup #1079's benchcase atfa7258221) mounted it:fileserver: mounted the DATA volume, 11 names. Evidence: https://github.com/ToyOSOrg/evidence/tree/f5f366507350e3edf5f1ab4fdd5408c2d9aa14ab/partitions/amdbench_data_designatedjudged PASS at0343c0aa8. Evidence: https://github.com/ToyOSOrg/evidence/tree/b4415902d279607eb788e57da9f4c0ec3aa690f8/partitions/t14nvme 04:00.0wrote and read back the stamp on p4 (44,564,480 blocks).NoHeader, noReadFailed). The scratch stick, whose table sgdisk wrote, reported no disagreement, so its backup on sector 60,062,499 read valid.fileserver: mounted the DATA volume, bcachefs, 11 names. Evidence: https://github.com/ToyOSOrg/evidence/tree/40689599401a34e6295a1ff0aa5ca6e7565dd560/partitions/t14Risks
/apps,/config,/homeand/stateabsent.bench_data_designatedis staged for the T14 and the AMD bench.system/supervisor/src/main.rs,make_session_homeon its file worker, bounded byFILES_MS). DATA's file server formats before its first answer, so the runner starts after the format.issues/a-first-format-interrupted-mid-flush-can-leave-a-superblock-over-a-bitmap-it-never-wrote.md.fileserver: mounted the DATA volume, bcachefs, 11 names. Filed asissues/a-stops-file-sync-and-its-failure-are-never-recorded.md.ReadFailedthere. Designation on a USB disk itself is host-tested only.🤖 Generated with Claude Code