docs: storage — the mount map is built; the path is the id (S2)
Flip the storage docs to match S2: filesystems.csv (signature -> binary) and volumes.csv (identity -> optional override) are built; a volume's mount path IS its content id (/volumes/<id>), never a port name; the label is display metadata a `volumes` query returns. fat receives its mount path via argv[2] rather than hardcoding it. Still pending: rung 2 (filesystem UUID, needs a non-FAT engine), multi-volume (fat's boot rewrites stay unconditional until S3), medium_changed consumption, remount bench-verification.
This commit is contained in:
@@ -3,18 +3,23 @@
|
||||
> **Status:** the layered model below is the settled design
|
||||
> ([storage-design-rationale.md](storage-design-rationale.md) records how it was
|
||||
> reached, and [volume-manager-plan.md](../volume-manager-plan.md) how it was
|
||||
> built). **Built** (the volume-manager track, V0–V4): the data path, the driver
|
||||
> built). **Built** (V0–V4 + the storage-stack S1/S2): the data path, the driver
|
||||
> range confinement (per-sender clamp + the confinement gate), the `medium_changed`
|
||||
> presence event, the volume manager itself — it probes the partition table,
|
||||
> confines each filesystem to its partition, spawns one filesystem per volume, and
|
||||
> supervises it — and the removal half of the lifecycle (a pulled stick unmounts).
|
||||
> **Still pending**: the fuller identity ladder and the `volumes.csv` mount map,
|
||||
> multi-volume (one FAT volume today), the volume manager *consuming*
|
||||
> `medium_changed` (removal is detected by device-presence polling; the event is
|
||||
> published but only a card-reader medium change needs the subscription), and the
|
||||
> remount-on-replug end-to-end (the logic is in place; QEMU can't re-present the
|
||||
> boot-controller device, so it is bench-verified). A few markers below are left
|
||||
> where a duty is still pending.
|
||||
> supervises it — the removal half of the lifecycle (a pulled stick unmounts), the
|
||||
> identity ladder (GPT GUID + name, FAT serial + label, MBR), and the mount map:
|
||||
> `filesystems.csv` (signature → binary) + `volumes.csv` (identity → optional
|
||||
> override), a volume's mount path IS its content id (`/volumes/<id>`), with the
|
||||
> label as display metadata a `volumes` query returns. **Still pending**: the
|
||||
> `filesystem UUID` rung (needs a non-FAT engine), multi-volume (one FAT volume
|
||||
> today; fat's boot rewrites are unconditional until S3 makes them
|
||||
> content-conditional), the volume manager *consuming* `medium_changed` (removal
|
||||
> is detected by device-presence polling; the event is published but only a
|
||||
> card-reader medium change needs the subscription), and the remount-on-replug
|
||||
> end-to-end (the logic is in place; QEMU can't re-present the boot-controller
|
||||
> device, so it is bench-verified). A few markers below are left where a duty is
|
||||
> still pending.
|
||||
|
||||
## The model
|
||||
|
||||
@@ -85,16 +90,17 @@ manager's tree for a storage provider; when one appears it consumer-hellos for
|
||||
the block channel, reads the partition table and the first blocks itself
|
||||
(**it** is the prober), defines the volume's sub-range on the driver, spawns the
|
||||
matching filesystem service confined to that range, and supervises it (backoff,
|
||||
crash-loop cap). *(Pending)*: it decides mount placement from `volumes.csv` and
|
||||
picks the filesystem binary from `filesystems.csv` — today it hands every
|
||||
FAT-shaped volume to the FAT service and the FAT service carries hardcoded mount
|
||||
prefixes. Those tables are CSV configuration, read by it (the policy), enforced
|
||||
by nobody else:
|
||||
crash-loop cap). *(Built)*: it picks the filesystem binary from
|
||||
`filesystems.csv` by the volume's content signature, and mounts the volume at its
|
||||
content id (`/volumes/<id>`) — or a `volumes.csv` override. The label is display
|
||||
metadata the `volumes` query returns, never the path. Those tables are CSV
|
||||
configuration, read by it (the policy), enforced by nobody else:
|
||||
|
||||
- `filesystems.csv` *(pending)* — content signature → filesystem binary. Adding
|
||||
- `filesystems.csv` *(built)* — content signature → filesystem binary. Adding
|
||||
a filesystem adds a row.
|
||||
- `volumes.csv` *(pending)* — the mount map, danos's fstab: **volume identity → mount
|
||||
prefix**, keyed on content identity and never on port, path, or arrival
|
||||
- `volumes.csv` *(built)* — the mount map, danos's fstab: an OPTIONAL **volume
|
||||
identity → mount prefix** override (a volume with no row mounts at its default
|
||||
`/volumes/<id>`), keyed on content identity and never on port, path, or arrival
|
||||
order (the lesson of Linux's `/dev/sda1`-era fstab, which broke on every
|
||||
port move until `UUID=` replaced it). Identity is read off the medium by
|
||||
the prober, strongest first: GPT partition GUID → filesystem UUID → FAT
|
||||
@@ -105,8 +111,8 @@ by nobody else:
|
||||
identity (cloned sticks, together) is policy: first keeps the name, the
|
||||
second mounts suffixed and is logged loudly. The boot volume is the
|
||||
recorded identity of the volume carrying `/system/configuration` and
|
||||
`/system/logs`, findable on any port. Unknown volumes mount under
|
||||
`/volumes/<derived name>`.
|
||||
`/system/logs`, findable on any port. Every volume's default mount is
|
||||
`/volumes/<id>` — its rendered content identity.
|
||||
|
||||
**Filesystem service** (the FAT service today; one process per volume): the
|
||||
proven unit — block-client + engine + file-protocol provider in one binary. It
|
||||
@@ -114,12 +120,13 @@ receives its block channel at spawn; it never discovers devices. It registers
|
||||
its own mounts with the kernel; its write cache lives inside the process, so a
|
||||
write error is observed by the code that owns the volume and surfaces on the
|
||||
owning channel (the anti-fsyncgate rule — never a system-wide dirty pool).
|
||||
*(Today, interim:)* fat still hardcodes its mount prefixes (`/volumes/usb` plus
|
||||
the two boot-volume hierarchy subtrees it rewrites in place); a `volumes.csv`
|
||||
mount map will migrate that to the volume manager. It no longer self-acquires a
|
||||
volume — the V3b flip made it receive its volume id at spawn and its block
|
||||
channel from the volume manager's hello reply, consistent with "it never
|
||||
discovers devices" above.
|
||||
*(Built:)* fat receives its mount path as `argv[2]` from the volume manager (the
|
||||
volume's id-path, e.g. `/volumes/fat-12345678`) and mounts its root there, plus
|
||||
the two `/system` hierarchy rewrites it installs in place (unconditional this
|
||||
increment; S3 makes them content-conditional across volumes). It no longer
|
||||
self-acquires a volume — the V3b flip made it receive its volume id and block
|
||||
channel from the volume manager, consistent with "it never discovers devices"
|
||||
above.
|
||||
|
||||
**Kernel** (mechanism only): the mount table routes paths to backend
|
||||
endpoints — resolve and redirect, never data. Remount-replace is the restart
|
||||
|
||||
Reference in New Issue
Block a user