Files
danos/docs/hot-plug-matrix-plan.md
T

55 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The hot-plug matrix: unplug anything, replug anywhere
*Status: COMPLETE, 2026-08-09, same day — H1..H5 all green, full suite 124/124.
The predicted cascade bug was real and found by H2: `tearDownPort` did not recurse
into a hub yanked from a root port, so its subtree stayed live against vanished
hardware and the replugged hub found its port occupied; fixed by mirroring
`tearDownHubDevice`'s children-first recursion (77e7001). Every other cell passed
against the establishment-track machinery unchanged.*
*2026-08-09. The requirement, verbatim: "i want to be able to unplug devices and
plug them back in, in any order and on any hub." The machinery exists end to end —
per-device driver processes, cascading teardown (`tearDownHubDevice` recurses a
departing hub's subtree, children first), reap-on-removal in the manager, idempotent
per-port registration identity, lineage rebinding — but only one cell of the matrix
is verified: a leaf keyboard behind a hub, unplugged and replugged on the same port
(`usb-hub-unplug`). This plan verifies the rest and fixes what verification flushes
out. The cascade path has never executed; expect it to carry at least one bug.*
**Out of scope, stated up front:** unplugging the BOOT stick (the drivers handle it;
fat holds a dead block channel until M21 remount gives it re-acquisition), and
real-hardware root-port timing (the Ryzen bench is the acceptance run for that, as
always — QEMU proves the logic, not the silicon).
## The discrimination lever
Every case's rebind tail (— reaping → delegated → second-generation `ok`) is
impossible without the manager's reap: stashing the reap out of
`onChildRemoved`/`pruneChildrenOf` makes every matrix case fail at the dedupe wall.
That is the standing discrimination check for the whole matrix — run it once per
case shape, not per commit.
## The matrix
| Case | Topology | Event sequence | What it proves |
|---|---|---|---|
| H1 `usb-root-replug` | keyboard on a 2nd controller's ROOT port | del @8s, add @14s (same port) | the `tearDownPort` path + reap + rebind; root-port changes arrive via the 250 ms reconcile tick (QEMU raises no root-port events) |
| H2 `usb-hub-yank` | hub on 2nd controller; keyboard AND mouse behind it | del the HUB @8s; re-add hub @14s, kbd @17s, mouse @18s | the recursive cascade: one event removes the subtree, EVERY bound driver is reaped, and the rebuilt hub re-binds both |
| H3 `usb-hub-nested-yank` | hub → hub → keyboard | del the OUTER hub @8s; re-add all three @14–18s | the cascade recursion depth ≥ 2, and a nested rebuild |
| H4 `usb-replug-moved` | keyboard behind hub port 1.1 | del @8s; add on port 1.2 @14s | a replug on a DIFFERENT port is simply a new device: new port identity, new id, fresh match — no stale state ties a driver to the old port |
| H5 `usb-replug-cycles` | keyboard behind hub | del/add three times (6 hooks) | no state leaks across generations: slots, the bus's open table, driver entries (reaped entries must be reusable) |
Ordered expects follow the `usb-hub-unplug` shape: the boot devices' `ok` lines all
precede the first unplug, so a tail of `removed → reaping → delegated → ok` can only
be satisfied by the generation the sequence created. H2/H3 require one `reaping` per
bound child; H5 requires three.
## Order and discipline
H1 → H2 → H3 → H4 → H5, one commit per case (plus its fix if it finds a bug — the
case and the fix land together, the case having failed first). The standing
discrimination run once for H1 and once for H2's shape. Full suite green at the end,
docs touched where behavior was corrected, memory updated. Fixes stay within the
settled design: teardown order (children first), reap-on-removal, identity per port
— anything design-shaped that surfaces stops the loop and asks.